如何检查值是否动态实现接口?

Kia*_*tad 1 reflection go

假设我有一个名为的接口Hello

type Hello interface {
   Hi() string
}

Run Code Online (Sandbox Code Playgroud)

我想编写一个获取Hello和任何接口的函数,n并在Hello实现n接口的情况下执行某些操作,例如:

type Person interface {
  Name() int
}

type Animal interface {
  Leg() int
}

type hello struct{}

func (h hello) Hi() string {
    return "hello!"
}

func (h hello) Leg() int {
    return 4
}

func worker() {
   h := hello{}

  // Doesn't match
  check(h,(Person)(nil))

  // Matches
  check(h,(Animal)(nil))
}

func check(h Hello, n interface{}) {
  // of course this doesn't work, should I use reflection, if so how?
  if _,ok := h.(n); ok {
      // do something 
  }
}
Run Code Online (Sandbox Code Playgroud)

如何实现该check功能?

bla*_*een 7

使用反射 Type.Implements

func check(n interface{}) bool {
    i := reflect.TypeOf(new(Hello)).Elem()
    return reflect.TypeOf(n).Implements(i)
}
Run Code Online (Sandbox Code Playgroud)

如果要用作引用的接口是已知的,则可以在向函数传递new(Hello)(*Hello)(nil)不传递额外参数的情况下对其进行实例化。

你不能使用,(Hello)(nil) 因为

如果 i 是一个 nil 接口,则TypeOf返回nil

否则,如果引用接口也是动态的,您可以将其作为参数传递。原理是一样的:

func main() {
     fmt.Println(check(new(Hello), new(Person))) // false
}

func check(i interface{}, n interface{}) bool {
    ti := reflect.TypeOf(i).Elem()
    return reflect.TypeOf(n).Implements(ti)
}
Run Code Online (Sandbox Code Playgroud)

游乐场:https : //play.golang.org/p/GYDcxtIobKc


在 Go 1.18(2022 年初)中将泛型添加到语言中后,您将能够为此编写一个使用类型断言的泛型函数:

如果T是接口类型,x.(T)则断言x实现接口的动态类型T

它看起来像:

func check[T any](i T, n interface{}) bool {
        _, ok := n.(T)
        return ok
}
Run Code Online (Sandbox Code Playgroud)

Go2 游乐场:https ://go2goplay.golang.org/p/HIBn3IYW13W