22

How can I ensure that a type implements an interface at compile time? The typical way to do this is by failure to assign to support interfaces from that type, however I have several types that are only converted dynamically. At runtime this generates very gruff error messages, without the better diagnostics given for compile time errors. It's also very inconvenient to find at run time that types I expected to support interfaces, do in fact not.

4

5 回答 5

30

假设问题是关于围棋的,例如

var _ foo.RequiredInterface = myType{} // or &myType{} or [&]myType if scalar

作为 TLD 将在编译时为您检查。

于 2012-05-08T12:56:09.733 回答
10

在 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.

详细阅读常见问题解答为什么 Go 没有“实现”声明?

于 2016-01-05T18:48:52.400 回答
8

通过@smile-on 扩展答案。

如何保证我的类型满足接口?,这是Go 作者的常见问题 (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)创建指向类型值的未初始​​化指针。请参阅无法理解一段 golang 代码Tnil*T

例如,这与var t *T分配任何内容之前的值相同。请参阅golang 接口合规性编译类型检查。这避免了为空结构分配内存,就像您使用&T{}or获得的那样new(T)。请参阅无法理解一段 golang 代码

报价已编辑以匹配示例。

于 2020-03-12T23:20:10.977 回答
-3
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

于 2014-08-15T09:15:55.093 回答
-6

我不喜欢通过在主代码中放置虚拟行来使编译器抛出错误的想法。这是一个有效的智能解决方案,但我更喜欢为此目的编写测试。

假设我们有:

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 编写测试。

于 2012-05-12T10:30:55.647 回答