Golang中的接口与鸭子类型

1 接口的定义与理解golang

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

    接口是彻底抽象的,所以不能将其实例化。然而,能够建立一个其类型为接口的变量,它能够被赋值为任何知足该接口类型的实际类型的值。接口的重要特性是:spa

   (1)只要某个类型实现了接口要的方法,那么咱们就说该类型实现了此接口。该类型的值能够赋给该接口的变量;指针

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

    注意:这只是golang中接口的特性,为非全部类型的特性(接口是一种特殊的类型)。继承

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


2 例子get

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)
}

运行结果
string

wKioL1YfYriDNBSMAACXshVCpYE028.jpg

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

    可是,特别注意一点。若是使用exchangeThese(pair1, pair2)会致使编译错误(以下图),正确写法应当是exchangeThese(&pair1, &pair2)。这是因为真正知足接口Exchanger的类型是StringPair指针,而非StringPair。

wKiom1YfY62whJPlAAFdgv-1E-c818.jpg

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

相关文章
相关标签/搜索