Golang中的接口与鸭子类型

说话的白菜 · · 3794 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

1 接口的定义与理解

聽 聽 接口是一个自定义类型,它是一组方法的集合。从定义上来看,接口有两个特点。第一,接口本质是一种自定义类型,因此不要将golang中的接口简单理解为C++/Java中的接口,后者仅用于声明方法签名。第二,接口是一种特殊的自定义类型,其中没有数据成员,只有方法(也可以为空)。

聽 聽 接口是完全抽象的,因此不能将其实例化。然而,可以创建一个其类型为接口的变量,它可以被赋值为任何满足该接口类型的实际类型的值。接口的重要特性是:

聽 聽(1)只要某个类型实现了接口要的方法,那么我们就说该类型实现了此接口。该类型的值可以赋给该接口的变量;

聽 聽(2)作为1的推论,任何类型的值都可以赋值给空接口interface{}

聽 聽 注意:这只是golang中接口的特性,为非所有类型的特性(接口是一种特殊的类型)。

聽 聽 接口的特性是golang支持鸭子类型的基础,即“如果它走起来像鸭子,叫起来像鸭子(实现了接口要的方法),它就是一只鸭子(可以被赋值给接口的值)”。凭借接口机制和鸭子类型,golang提供了一种游离于类、继承、模板之外的更加灵活强大的选择。


2 例子

type聽Exchanger聽interface聽{
聽聽聽聽聽聽聽exchange()
}
聽
type聽StringPair聽struct聽{
聽聽聽聽聽聽聽first,聽second聽string
}
聽
type聽Point[2]int
聽
func聽(sp聽*StringPair)聽exchange()聽{
聽聽聽聽聽聽聽sp.first,聽sp.second聽=聽sp.second,聽sp.first
}
聽
func聽(p聽*Point)聽exchange()聽{
聽聽聽聽聽聽聽p[0],聽p[1]聽=聽p[1],聽p[0]
}
聽
func聽exchangeThese(exchangers聽...Exchanger)聽{
聽聽聽聽聽聽聽for聽_,聽exchanger聽:=聽range聽exchangers聽{
聽聽聽聽聽聽聽聽聽聽聽聽聽聽exchanger.exchange()
聽聽聽聽聽聽聽}
}
聽
func聽main()聽{
聽聽聽聽聽聽聽pair1聽:=聽StringPair{"abc","def"}
聽聽聽聽聽聽聽pair2聽:=聽StringPair{"ghi","jkl"}
聽聽聽聽聽聽聽point聽:=聽Point{5,聽7}
聽
聽聽聽聽聽聽聽fmt.Println(pair1,聽pair2,聽point)
聽聽聽聽聽聽聽pair1.exchange()
聽聽聽聽聽聽聽pair2.exchange()
聽聽聽聽聽聽聽point.exchange()
聽聽聽聽聽聽聽fmt.Println(pair1,聽pair2,聽point)
聽
聽聽聽聽聽聽聽//聽exchangeThese(pair1,聽pair2)聽//wrong
聽聽聽聽聽聽聽exchangeThese(&pair1,聽&pair2)
聽聽聽聽聽聽聽fmt.Println(pair1,聽pair2)
}

运行结果

wKioL1YfYriDNBSMAACXshVCpYE028.jpg

聽 聽 在本例中,自定义类型StringPair和Point指针实现了接口Exchanger所需的方法,因此该类型的值可以被赋值给接口的值。

聽 聽 但是,特别注意一点。如果使用exchangeThese(pair1, pair2)会导致编译错误(如下图),正确写法应当是exchangeThese(&pair1, &pair2)。这是由于真正满足接口Exchanger的类型是StringPair指针,而非StringPair。

wKiom1YfY62whJPlAAFdgv-1E-c818.jpg

聽 聽 在golang值接收者和指针接收者的方法集是不同的。只是golang会智能地解引用和取引用,使得二者的方法集看上去是一样的。但是,在调用exchangeThese时,就凸显出二者的不同了。

本文出自 “说话的白菜” 博客,谢绝转载!


有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:说话的白菜

查看原文:Golang中的接口与鸭子类型

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3794 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传