简体   繁体   English

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

[英]Ensure a type implements an interface at compile time in Go

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.在运行时找到我希望支持接口的类型也很不方便,实际上不支持。

Assuming the question is about Go, eg假设问题是关于围棋,例如

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

as a TLD will check that for you at compile time.因为 TLD 会在编译时为您检查。

In the Go language there is no " implements " declaration by design.在 Go 语言中,设计上没有“实现”声明。 The only way to ask the compiler to check that the type T implements the interface I by attempting an assignment (yes, a dummy one).要求编译器通过尝试赋值来检查类型T实现了接口I的唯一方法(是的,一个虚拟的)。 Note, Go lang differentiates methods declared on structure and pointer, use the right one in the assignment check!注意,Go lang 区分在结构体和指针上声明的方法,在赋值检查中使用正确的方法

type T struct{}
var _ I = T{}       // Verify that T implements I.
var _ I = (*T)(nil) // Verify that *T implements I.

Read FAQ for details Why doesn't Go have "implements" declarations?阅读 FAQ 了解详情为什么 Go 没有“实现”声明?

Extending the answer by @smile-on.通过@smile-on 扩展答案。

In How can I guarantee my type satisfies an interface?我如何保证我的类型满足接口? , which is part of the Frequently Asked Questions (FAQ) by the Go Authors, the following is stated: ,这是 Go 作者的常见问题 (FAQ)的一部分,声明如下:

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.您可以通过尝试使用T的零值或指向T指针(视情况而定)来要求编译器检查类型T实现了接口I

We can illustrate this with an example:我们可以用一个例子来说明这一点:

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

If T (or *T , accordingly) doesn't implement I , the mistake will be caught at compile time.如果T (或*T ,相应地)没有实现I ,错误将在编译时被捕获。 See Non-interface methods in interface implementation .请参阅接口实现中的非接口方法

Typically you check if a value implements an interface if you don't know its type.通常,如果您不知道某个值的类型,则检查该值是否实现了接口。 If it is known, the check is done by the compiler automatically.如果已知,则检查由编译器自动完成。 See Explanation of checking if value implements interface .请参阅检查值是否实现接口的说明

The blank identifier _ stands for the variable name, which is not needed here (and thus prevents a "declared but not used" error).空白标识符_代表变量名,这里不需要它(从而防止“声明但未使用”错误)。 (*T)(nil) creates an uninitialized pointer to a value of type T by converting nil to *T . (*T)(nil)通过将nil转换为*T来创建一个指向T类型值的未初始​​化指针。 See Have trouble understanding a piece of golang code .请参阅理解一段 golang 代码时遇到问题

This is the same value which, for example, var t *T has before assigning anything to it.这与例如var t *T在分配任何内容之前具有的值相同。 See golang interface compliance compile type check .请参阅golang 接口合规性编译类型检查 This avoids allocation of memory for an empty struct as you'd get with &T{} or new(T) .这避免了像使用&T{}new(T)那样为空结构分配内存。 See Have trouble understanding a piece of golang code .请参阅理解一段 golang 代码时遇到问题

Quotes edited to match example.行情编辑以匹配示例。

Like this:像这样:

http://play.golang.org/p/57Vq0z1hq0 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()
}

Will yield:将产生:

prog.go:19: cannot convert new(Test) (type *Test) to type Saluter:
    *Test does not implement Saluter (missing SayBye method)
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()
    }
}

The code example is here: http://play.golang.org/p/22bgbYVV6q代码示例在这里: http : //play.golang.org/p/22bgbYVV6q

I don't like the idea of making compiler throw errors by putting dummy lines in the main code.我不喜欢通过在主代码中放置虚拟行来使编译器抛出错误的想法。 That's a smart solution that works, but I prefer to write a test for this purpose.这是一个有效的智能解决方案,但我更喜欢为此目的编写测试。

Assuming that we have:假设我们有:

type Intfc interface { Func() }
type Typ int
func (t Typ) Func() {}

This test makes sure Typ implements Intfc :此测试确保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)
    }
}

You can check all of your types and interfaces by adding them to TestTypes function.您可以通过将它们添加到TestTypes函数来检查所有类型和接口。 Writing tests for Go is introduced here .这里介绍为 Go 编写测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM