Golang筆記 4.2 go 接口

前言

我正在學習酷酷的 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 類型也有很廣到應用。

END


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章