零、前言
看到一段代码,发现以前没有这样来使用golang的interface,因此,写了一小段代码来验证。
一、问题
有一个struct,如何判断这个struct是否实现了某个函数。
举例说:
type GG struct { name string } func (g *GG)Get() { …… } func (g *GG)Set(name string) { …… } func (g *GG)……等等一堆函数
如何判断GG是否实现了Print()函数呢?
二、解决方法
1、查看源代码或者doc或者说明文档或者写邮件给代码的原作者等。这是人工方法,简单有效。
2、使用reflection方法。这也是现在常用的方法。代码在网上有很多,不举例了。这是自动方法。
3、使用接口。这也是本文要做的事情。基本思路是:
在自己的代码中定义一个私有的interface,在该interface中定义需要查询的代码,然后借用interface的typeassertion来判断。
package main import ( "fmt" ) type V1 struct { name string } func (v *V1) Print() { fmt.Printf("V1 name=%s\n",v.name) } type V2 struct { score int } func (v *V2) PPrint() { fmt.Printf("V2 score=%d\n",v.score) } func main() { type P interface { Print() // 需要是否实现了Print函数 } type PP interface { PPrint() // 需要是否实现了PPrint函数 } T := func(t interface{}) { // 判断函数 if v,ok := t.(P); ok { // 如果实现了P接口,也就是判断是否实现了Print函数 v.Print() // 判断后可以根据需要实现代码 } else if vv,ok2 := t.(PP); ok2 { // 如果实现了PP接口,也就是判断是否实现了PPrint函数 vv.PPrint() // 判断后可以根据需要实现代码 } } // 以下为测试代码 v1 := &V1{"Jack"} v2 := &V2{100} T(v1) T(v2) }
V1 name=Jack V2 score=100
最后,在测试中,需要注意的是:判断是否实现了某个interface,需要为interface{}类型,如果直接使用:
if t,ok := v1.(P);ok { …… }
会出现“invalid type assertion: v1.(<inter>) (non-interface type *V1 on left)”。
解决方法为:
var vv interface{} = v1 if t,ok := vv.(P);ok { …… }