Go言語でのInterfaceの可視性について
ちょっとハマったのでメモがてらまとめました。
Interfaceも通常のstruct等と同じく先頭が小文字で始まる場合に別パッケージで参照できないという点についてです。
ディレクトリ構成
example ├── factory1 │ └── factory.go ├── factory2 │ └── factory.go ├── main1.go └── main2.go
外部でinterface実装可能
Factory
インターフェースのCreate()
,Register()
ともに先頭が大文字でパッケージ外から参照可能なので、別のパッケージでインターフェースを実装することが出来ます。
// example/factory1/factory.go package factory1 type Factory interface { Create() Register() }
// example/main1.go package main import "./factory1" type BarFactory struct { } func (h BarFactory) Create() { } func (h BarFactory) Register() { } var _ factory1.Factory = (*BarFactory)(nil) func main() { f1 := BarFactory{} f1.Create() f1.Register() }
外部でinterface実装不可能
Factory
インターフェースと同じパッケージ内で実装したものなら、
外部パッケージから利用可能です。
ポイント
register()
は先頭小文字で不可視になっているため、外部パッケージからはCreate()
しか呼べないregister()
は先頭小文字で不可視になっているため、外部パッケージではインターフェースの実装ができない
//example/factory2/factory.go package factory2 type Factory interface { Create() register() // 別packageから参照不可能 } type FooFactory struct { } func (h FooFactory) Create() { h.register() } func (h FooFactory) register() { } var _ Factory = (*FooFactory)(nil)
// example/main2.go package main import "./factory2" func main() { f2 := factory2.FooFactory{} f2.Create() // ERROR: 不可視なので呼び出せない // f2.register() } type BazFactory struct { } func (b BazFactory) Create() { } func (b BazFactory) register() { } // ERROR: Factory.register()が不可視なのでinterface実装できない //var _ factory2.Factory = (*BazFactory)(nil)
おわり
あまりinterfaceを使う機会がなかったので、よくわかってなくてハマりました。
(単に使い方わかってなくて使い所がわかってなかっただけかもしれませんが・・・)
触りながら自己理解したので、もし認識違い等ありましたら指摘いただけると助かります。