1. 程式人生 > 其它 >golang interface介面

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