深入理解Go的interface
0. 引言
在 Golang 中,interface 是一個非常重要的概念和特性,之前寫過兩篇相關的文章:Golang 「泛型編程」,談一談 Golang 的 interface 和 reflect。然後在 Gopher China 2017 的會上又有一個關於 interface 的 topic: understanding golang interface(Gopher China) — youtube,作者是 Francesc。故在此做一個整理和補充。
1. What is Interface?
引用
In object-oriented programming, a protocol or interface is a common means for unrelated objects) to communicate with each other. These are definitions of methods) and values which the objects agree upon in order to co-operate. — wikipedia
這是 wikipedia 關於 protocal 的定義,將 interface 類比如 protocal 是一種非常助於理解的方式。protocol,中文一般叫做協議,比如網路傳輸中的 TCP 協議。protocol 可以認為是一種雙方為了交流而做出的約定,interface 可以類比如此。
在 Golang 中,interface 是一種抽象類型,相對於抽象類型的是具體類型(concrete type):int,string。如下是 io 包裡面的例子。
// Writer is the interface that wraps the basic Write method. // // Write writes len(p) bytes from p to the underlying data stream. // It returns the number of bytes written from p (0 >= 1 { maxDepth++ } maxDepth *= 2 quickSort(data, 0, n, maxDepth) }
Sort 函數的形參是一個 interface,包含了三個方法:Len(),Less(i,j int),Swap(i, j int)。使用的時候不管數組的元素類型是什麼類型(int, float, string…),只要我們實現了這三個方法就可以使用 Sort 函數,這樣就實現了「泛型編程」。有一點比較麻煩的是,我們需要將數組自定義一下。下面是一個例子。
type Person struct { Name stringAge int } func (p Person) String() string { return fmt.Sprintf("%s: %d", p.Name, p.Age) } // ByAge implements sort.Interface for []Person based on // the Age field. type ByAge []Person //自定義 func (a ByAge) Len() int { return len(a) } func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a ByAge) Less(i, j int) bool { return a[i].Age
另外 Fransesc 在 Gopher China 上還提到了一個比較有趣的東西和大家分享一下。在我們設計函數的時候,下面是一個比較好的準則。
Be conservative in what you send, be liberal in what you accept. — Robustness Principle
對應到 Golang 就是:
Return concrete types, receive interfaces as parameter. — Robustness Principle applied to Go
話說這麼說,但是當我們翻閱 Golang 源碼的時候,有些函數的返回值也是 interface。
2.2 hiding implement detail
隱藏具體實現,這個很好理解。比如我設計一個函數給你返回一個 interface,那麼你只能通過 interface 裡面的方法來做一些操作,但是內部的具體實現是完全不知道的。Francesc 舉了個 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。
// newCancelCtx returns an initialized cancelCtx. func newCancelCtx(parent Context) cancelCtx { return cancelCtx{ Context: parent, done: make(chan struct{}), } } // A cancelCtx can be canceled. When canceled, it also cancels any children // that implement canceler. type cancelCtx struct { Context done chan struct{} // closed by the first cancel call. mu sync.Mutex children map[canceler]struct{} // set to nil by the first cancel call err error // set to non-nil by the first cancel call}func (c *cancelCtx) Done()
※懶人設計師必須知道的外部免費資源網站
※分時租賃企業「Ponycar」宣布獲1.5億B輪融資,投資方為惠友和OPPO
※二叉樹的那些使用
※Docker用以提高Linux內核安全性的三大熱點技術
※在迷茫中堅守的Neri,可能是惠普企業的最後一位高管
TAG:推酷 |
※MapReduce Shuffle深入理解
※從One-hot,Word embedding到Transformer,一步步教你理解Bert
※徹底理解cookie、session、token
※Windows PowerShell進階 理解Module
※理解 Linux 中的 /etc/services 文件
※我所理解的#ShotoniPhone
※理解foreach, for in, for of 之間的異同
※Glibc堆漏洞利用基礎-深入理解ptmalloc2 part1
※快速理解Token,Cookie,Session
※深入理解 Web Server 原理與實踐:Nginx
※深入理解 ES Modules
※Cookie,Session和Token概念的正確理解
※理解 OutOfMemoryError 異常
※「straight from the horse s mouth」不是「從馬的嘴」,這樣理解就錯了
※理解 Python 的 for 循環
※阿里CEO張勇:我們理解AI是Alibaba Intelligence
※簡單理解Vue中的nextTick
※我所理解的 Smartisan OS
※徹底理解 Node.js 中的回調(Callback)函數
※通過 Q-learning 深入理解強化學習