golang interface介面
如果說goroutine和channel是Go併發的兩大基石,那麼介面是Go語言程式設計中資料型別的關鍵。在Go語言的實際程式設計中,幾乎所有的資料結構都圍繞介面展開,介面是Go語言中所有資料結構的核心。
Go不是一種典型的OO語言,它在語法上不支援類和繼承的概念。
沒有繼承是否就無法擁有多型行為了呢?答案是否定的,Go語言引入了一種新型別—Interface,它在效果上實現了類似於C++的“多型”概念,雖然與C++的多型在語法上並非完全對等,但至少在最終實現的效果上,它有多型的影子。
雖然Go語言沒有類的概念,但它支援的資料型別可以定義對應的method(s)。本質上說,所謂的method(s)其實就是函式,只不過與普通函式相比,這類函式是作用在某個資料型別上的,所以在函式簽名中,會有個receiver(接收器)來表明當前定義的函式會作用在該receiver上。
Go語言支援的除Interface型別外的任何其它資料型別都可以定義其method(而並非只有struct才支援method),只不過實際專案中,method(s)多定義在struct上而已。 從這一點來看,我們可以把Go中的struct看作是不支援繼承行為的輕量級的“類”。
從語法上看,Interface定義了一個或一組method(s),這些method(s)只有函式簽名,沒有具體的實現程式碼(有沒有聯想起C++中的虛擬函式?)。若某個資料型別實現了Interface中定義的那些被稱為"methods"的函式,則稱這些資料型別實現(implement)了interface。這是我們常用的OO方式,如下是一個簡單的示例
type MyInterface interface{ Print() } func TestFunc(x MyInterface) {} type MyStruct struct {} func (me MyStruct) Print() {} func main() { var me MyStruct TestFunc(me) }
Why Interface
為什麼要用介面呢?在Gopher China 上的分享中,有大神給出了下面的理由:
writing generic algorithm (泛型程式設計)
hiding implementation detail (隱藏具體實現)
providing interception points
下面大體再介紹下這三個理由
writing generic algorithm (泛型程式設計)
嚴格來說,在 Golang 中並不支援泛型程式設計。在 C++ 等高階語言中使用泛型程式設計非常的簡單,所以泛型程式設計一直是 Golang 詬病最多的地方。但是使用 interface 我們可以實現泛型程式設計,如下是一個參考示例
package sort // A type, typically a collection, that satisfies sort.Interface can be // sorted by the routines in this package. The methods require that the // elements of the collection be enumerated by an integer index. type Interface interface { // Len is the number of elements in the collection. Len() int // Less reports whether the element with // index i should sort before the element with index j. Less(i, j int) bool // Swap swaps the elements with indexes i and j. Swap(i, j int) } ... // Sort sorts data. // It makes one call to data.Len to determine n, and O(n*log(n)) calls to // data.Less and data.Swap. The sort is not guaranteed to be stable. func Sort(data Interface) { // Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached. n := data.Len() maxDepth := 0 for i := n; i > 0; i >>= 1 { maxDepth++ } maxDepth *= 2 quickSort(data, 0, n, maxDepth) } 複製程式碼
Sort 函式的形參是一個 interface,包含了三個方法:Len(),Less(i,j int),Swap(i, j int)。使用的時候不管陣列的元素型別是什麼型別(int, float, string…),只要我們實現了這三個方法就可以使用 Sort 函式,這樣就實現了“泛型程式設計”
hiding implementation detail (隱藏具體實現)
隱藏具體實現,這個很好理解。比如我設計一個函式給你返回一個 interface,那麼你只能通過 interface 裡面的方法來做一些操作,但是內部的具體實現是完全不知道的。
例如我們常用的context包,就是這樣的,context 最先由 google 提供,現在已經納入了標準庫,而且在原有 context 的基礎上增加了:cancelCtx,timerCtx,valueCtx。
剛好前面我們有專門說過context,現在再來回顧一下
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { c := newCancelCtx(parent) propagateCancel(parent, &c) return &c, func() { c.cancel(true, Canceled) } } 複製程式碼
表明上 WithCancel 函式返回的還是一個 Context interface,但是這個 interface 的具體實現是 cancelCtx struct。
參考:
https://blog.csdn.net/weixin_34007020/article/details/88025102