Go Interfaceを満たしているか?

Posted on
go

var _ Foo = (*foo)(nil) みたいな記述を見かけて何だろうなと気になっていました。

How can I guarantee my type satisfies an interface?に書いてありました。

You can ask the compiler to check that the type T implements the interface I by attempting an assignment using the zero value for T or pointer to T, as appropriate:

type T struct{} var _ I = T{} // Verify that T implements I. var _ I = (*T)(nil) // Verify that *T implements I. If T (or *T, accordingly) doesn’t implement I, the mistake will be caught at compile time.

作成する構造体がその型を満たしているかチェックするためなんですね。

// funcの引数がポインタの場合
type Foo interface {
	Foo() string
}

type foo struct{}

func NewFoo() Foo {
	return &foo{}
}

var _ Foo = (*foo)(nil) // <- interface Fooを満たさないとコンパイルできない

func (t *foo) Foo() string {
	return "foo"
}

// Funcの引数が値の場合
type Bar interface {
	Bar() string
}

type bar struct{}

func NewBar() Bar {
	return bar{}
}

func (b bar) Bar() string {
	return "bar"
}

var _ Bar = bar{}  // <- interface Barを満たさないとコンパイルできない

ただまあNewの引数でもコンパイルエラー出ますし、IDEによって警告が出るのでFAQに書いてあるように基本的には必要ないという考え方なんでしょうね。

Most code doesn’t make use of such constraints, since they limit the utility of the interface idea. Sometimes, though, they’re necessary to resolve ambiguities among similar interfaces.

複雑な名前で似たようなメソッドを持っていて、勘違いが発生しそうな場合。。プログラムが広大になっていったら欲しく感じるんでしょうか。