确保类型在Go中的编译时实现接口

时间:2012-05-08 12:23:18

标签: types interface compiler-errors go

如何确保类型在编译时实现接口?执行此操作的典型方法是无法从该类型分配支持接口,但是我有几种仅动态转换的类型。在运行时,这会生成非常粗暴的错误消息,而没有为编译时错误提供更好的诊断。在运行时找到我希望支持接口的类型也很不方便,事实上并非如此。

6 个答案:

答案 0 :(得分:13)

假设问题是关于Go,例如

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

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

编辑:s / [*] /& /

EDIT2:s / dummy / _ /,感谢Atom

答案 1 :(得分:6)

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

阅读常见问题解答了解详情Why doesn't Go have "implements" declarations?

答案 2 :(得分:5)

通过@ smile-on扩展答案。

How can I guarantee my type satisfies an interface?中,它是Go Authors的Frequently Asked 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,则错误将在编译时捕获。参见Non-interface methods in interface implementation

通常,如果您不知道值的类型,则检查该值是否实现了接口。如果已知,则检查由编译器自动完成。参见Explanation of checking if value implements interface

空白标识符_代表变量名,这里不需要使用变量名(这样可以防止出现“已声明但未使用”错误)。 (*T)(nil)通过将T转换为nil,创建指向类型*T的值的未初始​​化指针。参见Have trouble understanding a piece of golang code

这是与var t *T相同的值,然后再为其分配任何内容。参见golang interface compliance compile type check。这样可以避免像使用&T{}new(T)那样为空结构分配内存。参见Have trouble understanding a piece of golang code

已编辑报价以匹配示例。

答案 3 :(得分:1)

像这样:

http://play.golang.org/p/57Vq0z1hq0

package main

import(
    "fmt"
)

type Test int

func(t *Test) SayHello() {
    fmt.Println("Hello");   
}

type Saluter interface{
    SayHello()
    SayBye()
}

func main() {
    t := Saluter(new(Test))
    t.SayHello()
}

将屈服:

prog.go:19: cannot convert new(Test) (type *Test) to type Saluter:
    *Test does not implement Saluter (missing SayBye method)

答案 4 :(得分:-1)

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

答案 5 :(得分:-3)

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

假设我们有:

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