使用interface与类型诊断机制判断一个类型是否实现了某个方法
Golang中的interface通常用来定义接口,在接口里提供一些方法,其他类型可以实现(implement)这些方法,通过将接口指针指向不同的类型实例实现多态(polymorphism),这是interface常见的应用场景。
Golang语言还提供了类型诊断机制(type assertion),将类型诊断与interface两者相结合就可以用来判断一个类型是否实现了某个方法。
基本思路是:在需要做判断的代码里定义一个私有的interface,在这个interface里定义唯一的一个方法(待判断的那个方法),通过应用类型诊断机制判断是否实现了这个方法。
代码示例
package main import ( "fmt" ) type Foo struct { //... } type BigFoo struct { // ... } func (this *BigFoo)Eat() string { return "eat food!" } func sample() { type Fooer interface { Eat() string } Assertor := func(t interface{}) { // 是否是Fooer接口,间接判断是否实现了Eat方法 if tmp, ok := t.(Fooer); ok { fmt.Printf("%T:%s\n", t, tmp.Eat()) // 调用方法 } else { fmt.Printf("%T not implement Eat() method\n", t) } } foo := &Foo{} bigFoo := &BigFoo{} Assertor(foo) Assertor(bigFoo) } func main() { sample() }
运行上面代码后的输出如下:
*main.Foo not implement Eat() method
*main.BigFoo:eat food!
通过类型诊断机制判断是否是某个interface,间接判断是否实现了待判断的那个方法。
注意事项
如果直接使用:
if tmp, ok := foo.(Fooer); ok { // }
编辑器会出现 “Invalid type assertion: foo.(Fooer) (non-interface type *Foo on left)” 的提示,解决办法是将值转型成 interface{} 然后再运用类型诊断。
var tempFoo interface{} = foo if tmp, ok := tempFoo.(Fooer); ok { // }
判断是否实现了某个方法还有其他方式,比如使用reflection、查看源代码等。