Upgrade to Pro — share decks privately, control downloads, hide ads and more …

【登壇資料】Goの内部実装に学ぶ、メソッド隠蔽とその活用

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for エブリー エブリー
December 05, 2025
370

 【登壇資料】Goの内部実装に学ぶ、メソッド隠蔽とその活用

20251205 layerx go

Avatar for エブリー

エブリー

December 05, 2025
Tweet

More Decks by エブリー

Transcript

  1. 3 Copyright © 2015 every, Inc. All rights reserved. 自己紹介

    名前:赤川 正朋 (X: まさとも @mathatomo57) 所属:株式会社エブリー 開発1部(2025.4~) 担当:ヘルシカ(健康管理アプリ)のバックエンド 主な技術領域: Go、 AWS、最近は認証認可周り Go歴:1年ちょっと 学生の時は数学をやっていました 最近社内で Goの勉強会を始めました。 知見ある方いたら懇親会でお話ししたいです!
  2. 5 Copyright © 2015 every, Inc. All rights reserved. Goの埋め込みの基本

    • Goでは構造体に型を埋め込むことができる • 構造体は埋め込まれた型のフィールドやメソッドをあたかも自分のもののように使える (promoted) サンプルコードにはなるべくQR コード付けたので、必要に応じ て読み取ってください https://go.dev/play/p/UPx633_DuYZ
  3. 6 Copyright © 2015 every, Inc. All rights reserved. promotedの定義

    specより引用 A field or method f of an embedded field in a struct x is called promoted if x.f is a legal selector that denotes that field or method f. 構造体内の埋め込まれたフィールド x のフィールドまたはメソッド f は、x.f が f を表すlegalな selectorである場合に promotedと呼ぶ。
  4. 7 Copyright © 2015 every, Inc. All rights reserved. legal

    selectorの定義 specより引用 For a value x of type T or *T where T is not a pointer or interface type, x.f denotes the field or method at the shallowest depth in T where there is such an f. If there is not exactly one f with shallowest depth, the selector expression is illegal. 型 T または *T の値 x について(ここで T はポインタ型でもインターフェース型でもない)、 x.f は T において f という名前のフィールドまたはメソッドが存在する 最も浅い深さ のものを指す。最も 浅い深さに f が一つだけ存在しない場合、この selectorはillegalである。 つまり…
  5. 11 Copyright © 2015 every, Inc. All rights reserved. ということが、Effective

    Go にも書いてあった Embedding types introduces the problem of name conflicts but the rules to resolve them are simple. First, a field or method X hides any other item X in a more deeply nested part of the type. 埋め込み型は名前衝突の問題を引き起こすが、これを解決するルールは単純である。まず、 フィールドまたはメソッド X は、型内のより深くネストされた部分にある他の項目 X を隠す。
  6. 12 Copyright © 2015 every, Inc. All rights reserved. ということが、Effective

    Go にも書いてあった Second, if the same name appears at the same nesting level, it is usually an error; (中 略)However, if the duplicate name is never mentioned in the program outside the type definition, it is OK. (中略) there is no problem if a field is added that conflicts with another field in another subtype if neither field is ever used. 第二に、同じネストレベルで同じ名前が現れる場合、通常はエラーとなる。(中略)ただし、重複す る名前が型定義の外でプログラム内で一切言及されない場合は問題ない。(中略)別のサブタイ プ内のフィールドと競合するフィールドが追加されても、いずれのフィールドも使用されない限り問 題はない。
  7. 14 Copyright © 2015 every, Inc. All rights reserved. ドットファイルを除いたファイルシステム

    Readdirメソッドを上書きして、ドットファイルを無視している https://github.com/golang/go/blob/4d0658bb/src/net/http/example_filesystem_test.go
  8. 15 Copyright © 2015 every, Inc. All rights reserved. ドットファイルを除いたファイルシステム

    ドットファイルが含まれていたらエラー、そうでないなら dotFileHidingFileにラップして returnする ようOpenを上書き https://github.com/golang/go/blob/4d0658bb/src/net/http/example_filesystem_test.go
  9. 17 Copyright © 2015 every, Inc. All rights reserved. Fileの書き込みでの例

    noWriteToからpanicするだけの WriteToメソッドが生えていて、 fileWithoutWriteToに埋め込まれている https://github.com/golang/go/blob/master/src/os/file.go
  10. 18 Copyright © 2015 every, Inc. All rights reserved. Fileの書き込みでの例

    元のWriteToメソッドは中で genericWriteToを呼び出していて、 io.CopyにfileWithOutWriteToを渡している https://github.com/golang/go/blob/master/src/os/file.go
  11. 19 Copyright © 2015 every, Inc. All rights reserved. Fileの書き込みでの例

    io.Copyの中では再び WriteToが呼び出されている つまり、素直に Fileを渡すと無限ループに陥ってしまう! https://github.com/golang/go/blob/master/src/io/io.go 他にも、tcpConnでも同様の実装が見られる
  12. 20 Copyright © 2015 every, Inc. All rights reserved. 上書き、隠蔽は実装で使えるのか?

    • パッケージなどで既に用意されている構造体をカスタムして扱う場合には有効 • わかりづらいので noWriteToほどのことはやらない方が良い • 特定のメソッドを隠蔽するくらいなら、小さいメソッド集合を持つ構造体を複数用意して埋め込 む方がわかりやすい(と、自分は思っています) • 複数のメソッドの上書き、隠蔽は構造体をどう命名したら良いのかわからないのでやりたくな い
  13. 21 Copyright © 2015 every, Inc. All rights reserved. 自分の中での結論

    隠蔽・上書きするメソッドは 1つだけにして、構造 体にわかりやすい命名を!