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
在本例中,自定義類型StringPair和Point指針實現了接口Exchanger所需的方法,所以該類型的值能夠被賦值給接口的值。it
可是,特別注意一點。若是使用exchangeThese(pair1, pair2)會致使編譯錯誤(以下圖),正確寫法應當是exchangeThese(&pair1, &pair2)。這是因爲真正知足接口Exchanger的類型是StringPair指針,而非StringPair。
在golang中,值接收者和指針接收者的方法集是不一樣的。只是golang會智能地解引用和取引用,使得兩者的方法集看上去是同樣的。可是,在調用exchangeThese時,就凸顯出兩者的不一樣了。