前言
我正在學習酷酷的 Golang,可點此查看帖子Golang學習筆記彙總。
1 它是什麼
說背景和地位
摘錄自《go語言編程》
接口在Go語言有着至關重要的地位。如果說goroutine和channel 是支撐起Go語言的併發模型的基石,讓Go語言在如今集羣化與多核化的時代成爲一道極爲亮麗的風景,那麼接口是Go語言整個類型系統的基石,讓Go語言在基礎編程哲學的探索上達到前所未有的高度。
Go語言在編程哲學上是變革派,而不是改良派。這不是因爲Go語言有goroutine和channel,而更重要的是因爲Go語言的類型系統,更是因爲Go語言的接口。 Go語言的編程哲學因爲有接口而趨近完美。
Go語言的非侵入式接口,看似只是做了很小的文法調整,實則影響深遠。
侵入式接口,“侵入式”的主要表現在於實現類需要明確聲明自己實現了某個接口。
一句話說明
接口提供了一種方式來說明對象的行爲:如果誰能搞定這件事,它就可以用在這兒。
接口定義了一組方法(方法集),但是這些方法不包含(實現)代碼:它們沒有被實現(它們是抽象的)。
所以一句話來說,接口是使用方法的抽象。
2 爲什麼需要它
接口是使用方法的抽象,使當前程序可以更聚焦在方法的應用,不關心該方法的具體實現。
3 怎麼用
接口賦值
接口定義:
type Integer int
func (a Integer) Less(b Integer) bool {
return a < b
}
func (a *Integer) Add(b Integer) {
*a += b
}
type LessAdder interface {
Less(b Integer) bool
Add(b Integer)
}
接口賦值,將實例賦值給接口:
var a Integer = 1
var b LessAdder = &a
接口查詢
var file1 Writer = ...
if file5, ok := file1.(two.IStream); ok {
...
}
Writer接口的實現實例file1,是否實現了 two.IStream 接口,如果實現了則執行代碼。
類型查詢
在 Go 語言中,還可以更加直截了當地詢問接口指向的對象實例的類型。
利用反射也可以進行類型查詢,詳情可參閱reflect.TypeOf()方法。
var v1 interface{} = ...
switch v := v1.(type) {
case int: // 現在v的類型是int
case string: // 現在v的類型是string
...
}
接口組合
type ReadWriter interface {
Reader
Writer
}
這個接口組合了Reader和Writer兩個接口,它完全等同於如下寫法:
type ReadWriter interface {
Read(p []byte) (n int, err error)
Write(p []byte) (n int, err error)
}
4 示例
典型示例 關注使用,不操心接口實現。來自於《GO示例學》。
// 這裏定義了一個最基本的表示幾何形狀的方法的接口
type geometry interface {
area() float64
perim() float64
}
// 這裏不管正方形或者長方形怎麼去實現自己的接口,但最後使用部分,直接用接口方法就好了。
func measure(g geometry) {
fmt.Println(g)
fmt.Println(g.area())
fmt.Println(g.perim())
}
5 空接口 Any類型
由於Go語言中任何對象實例都滿足空接口interface{},所以interface{}看起來像是可以指向任何對象的 Any 類型,如下:
var v1 interface{} = 1 // 將int類型賦值給interface{}
var v2 interface{} = "abc" // 將string類型賦值給interface{}
var v3 interface{} = &v2 // 將*interface{}類型賦值給interface{}
var v4 interface{} = struct{ X int }{1}
var v5 interface{} = &struct{ X int }{1}
當函數可以接受任意的對象實例時,我們會將其聲明爲interface{},最典型的例子是標準庫 fmt 中 PrintXXX 系列的函數,例如:
傳入參數是 可變數量的 任意類型。
func Printf(fmt string, args ...interface{})
func Println(args ...interface{})
總體來說, 我們剛開始對 interface{} 一無所知,但可以通過接口查詢和類型查詢逐步瞭解它。
6 小結
總結,接口是使用方法的抽象,使當前程序可以更聚焦在方法的應用,不關心該方法的具體實現。後續的應用程序在做具體實現時,再去完善具體實現,不會影響之前程序已經定義好的邏輯。
更通俗地來講,接口的定義,就像是設置了一個崗位,描述了崗位的職責;,一些規章可以先根據崗位職責來制定,不關心具體是誰來任職這個崗位。當應用程序開始執行的時候,需要給接口傳入一個實例,相當於企業開始運營時再把一個人放到這個崗位。
另外空接口 interface{} 作爲 Any 類型也有很廣到應用。