Go 問答之如何理解 Go 中的接口

如何理解 Golang 中的接口。我的認爲,要理解 Go 的接口,必定先了解下鴨子模型。bash

鴨子模型

那什麼鴨子模型?函數

鴨子模型的解釋,一般會用了一個很是有趣的例子,一個東西到底是不是鴨子,取決於它的能力。游泳起來像鴨子、叫起來也像鴨子,那麼就能夠是鴨子。spa

動態語言,好比 Python 和 Javascript 自然支持這種特性,不過相對於靜態語言,動態語言的類型缺少了必要的類型檢查。設計

Go 接口設計和鴨子模型有密切關係,但又和動態語言的鴨子模型有所區別,在編譯時,便可實現必要的類型檢查。code

什麼是 Go 接口

Go 接口是一組方法的集合,能夠理解爲抽象的類型。它提供了一種非侵入式的接口。任何類型,只要實現了該接口中方法集,那麼就屬於這個類型。接口

舉個例子,假設定義一個鴨子的接口。以下:ip

type Duck interface {
	Quack()   // 鴨子叫
	DuckGo()  // 鴨子走
}
複製代碼

假設如今有一個雞類型,結構以下:get

type Chicken struct {
}

func (c Chicken) IsChicken() bool {
	fmt.Println("我是小雞")
}
複製代碼

這隻雞和通常的小雞不同,它比較聰明,也能夠作鴨子能作的事情。string

func (c Chicken) Quack() {
	fmt.Println("嘎嘎")
}

func (c Chicken) DuckGo() {
	fmt.Println("大搖大擺的走")
}
複製代碼

注意,這裏只是實現了 Duck 接口方法,並無將雞類型和鴨子接口顯式綁定。這是一種非侵入式的設計。it

咱們定義一個函數,負責執行鴨子能作的事情。

func DoDuck(d Duck) {
	d.Quack()
	d.DuckGo()
}
複製代碼

由於小雞實現了鴨子的全部方法,因此小雞也是鴨。那麼在 main 函數中就能夠這麼寫了。

func main() {
	c := Chicken{}
	DoDuck(c)
}
複製代碼

執行正常。如此是否是很相似於其餘語言的多態,其實這就是 Go 多態的實現方法。

空接口

簡單說下空 interface。

若是一個 interface 中若是沒有定義任何方法,即爲空 interface,表示爲 interface{}。如此一來,任何類型就都能知足它,這也是爲何當函數參數類型爲 interface{} 時,能夠給它傳任意類型的參數。

示例代碼,以下:

package main

import "fmt"

func main() {
	var i interface{} = 1
	fmt.Println(i)
}
複製代碼

更經常使用的場景,Go 的 interface{} 經常會被做爲函數的參數傳遞,用以幫助咱們實現其餘語言中的泛型效果。Go 中暫時不支持 泛型,不過 Go 2 的方案中彷佛將支持泛型。

總結

回答結束,作個簡單總結。

理解 Go 接口要記住一點,接口是一組方法的集合,這句話很是重要,理解了這句話,再去理解 Go 的其餘知識,好比類型、多態、空接口、反射、類型檢查與斷言等就會容易不少。

相關文章
相關標籤/搜索