使用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、查看源代码等。

posted @ 2019-04-12 15:49  AIData  阅读(543)  评论(0编辑  收藏