型がコンパイル時にインターフェイスを実装していることを確認するにはどうすればよいですか?これを行う一般的な方法は、そのタイプのサポートインターフェイスへの割り当てに失敗することですが、動的にのみ変換されるタイプがいくつかあります。実行時に、これは非常に不機嫌なエラーメッセージを生成しますが、コンパイル時エラーに対してより適切な診断が提供されることはありません。また、実行時に、インターフェイスをサポートすると期待していたタイプが実際にはサポートされていないことを見つけるのは非常に不便です。
5 に答える
質問がGoに関するものであると仮定すると、たとえば
var _ foo.RequiredInterface = myType{} // or &myType{} or [&]myType if scalar
TLDは、コンパイル時にそれをチェックします。
Go言語では、設計による「実装」宣言はありません。T
型が割り当てを試みることによってインターフェースを実装していることを確認するようにコンパイラーに要求する唯一の方法I
(はい、ダミーのもの)。Go langは、構造体とポインターで宣言されたメソッドを区別します。割り当てチェックでは正しいメソッドを使用してください。
type T struct{}
var _ I = T{} // Verify that T implements I.
var _ I = (*T)(nil) // Verify that *T implements I.
詳細についてはFAQをお読みくださいGoに「実装」宣言がないのはなぜですか?
@smile-onによる答えの拡張。
タイプがインターフェースを満たすことをどのように保証できますか?、GoAuthorsによるFrequentlyAsked Questions(FAQ)の一部である、次のように述べられています。
必要に応じて、のゼロ値またはへのポインタを使用して割り当てを試行することにより、型
T
がインターフェイスを実装していることを確認するようにコンパイラに要求できます。I
T
T
これを例で説明できます。
package main
type I interface{ M() }
type T struct{}
func (T) M() {}
//func (*T) M() {} //var _ I = T{}: T does not implement I (M method has pointer receiver)
func main() {
//avoids allocation of memory
var _ I = T{} // Verify that T implements I.
var _ I = (*T)(nil) // Verify that *T implements I.
//allocation of memory
var _ I = &T{} // Verify that &T implements I.
var _ I = new(T) // Verify that new(T) implements I.
}
T
(または*T
、それに応じて)が実装されていない場合I
、コンパイル時に間違いが検出されます。インターフェイス実装の非インターフェイスメソッドを参照してください。
通常、値のタイプがわからない場合は、値がインターフェイスを実装しているかどうかを確認します。既知の場合、チェックはコンパイラーによって自動的に行われます。値がインターフェイスを実装しているかどうかのチェックの説明を参照してください。
空白の識別子_
は変数名を表します。これはここでは必要ありません(したがって、「宣言されているが使用されていない」エラーを防ぎます)。に変換することにより、(*T)(nil)
typeの値への初期化されていないポインタを作成します。golangコードの一部を理解するのに問題があるを参照してください。T
nil
*T
これは、たとえば、var t *T
何かを割り当てる前に持っている値と同じです。golangインターフェースコンプライアンスコンパイルタイプチェックを参照してください。&T{}
これにより、またはで取得するような空の構造体へのメモリの割り当てが回避されますnew(T)
。golangコードの一部を理解するのに問題があるを参照してください。
例に一致するように編集された引用。
package main
import (
"fmt"
)
type Sayer interface {
Say()
}
type Person struct {
Name string
}
func(this *Person) Say() {
fmt.Println("I am", this.Name)
}
func main() {
person := &Person{"polaris"}
Test(person)
}
func Test(i interface{}) {
//!!here ,judge i implement Sayer
if sayer, ok := i.(Sayer); ok {
sayer.Say()
}
}
コード例は次のとおりです:http://play.golang.org/p/22bgbYVV6q
メインコードにダミー行を入れてコンパイラにエラーをスローさせるというアイデアは好きではありません。これは機能するスマートなソリューションですが、私はこの目的のためにテストを作成することを好みます。
私たちが持っていると仮定すると:
type Intfc interface { Func() }
type Typ int
func (t Typ) Func() {}
このテストでは、Typ
実装が次のことを確認しますIntfc
。
package main
import (
"reflect"
"testing"
)
func TestTypes(t *testing.T) {
var interfaces struct {
intfc Intfc
}
var typ Typ
v := reflect.ValueOf(interfaces)
testType(t, reflect.TypeOf(typ), v.Field(0).Type())
}
// testType checks if type t1 implements interface t2
func testType(t *testing.T, t1, t2 reflect.Type) {
if !t1.Implements(t2) {
t.Errorf("%v does not implement %v", t1, t2)
}
}
関数に追加することで、すべてのタイプとインターフェースを確認できますTestTypes
。Goのライティングテストはここで紹介されています。