【Go】接口的定義與使用

Go 裏面的接口,絕對是我入坑程序員以來覺得最坑的一個東西了。爲什麼說它坑,就是怎麼看怎麼彆扭。

說明

Go 中的接口是由使用者來定義的。這和傳統的 接口 有點不一樣(當然我們在開發的過程中可以根據具體的情況去決定誰用接口)

看一個例子:

// package mooc
type Retriever struct {
	Contents string
}
func (r Retriever) Get(url string) string {
	return r.Contents
}
// package main
type Retriever interface {
	Get(url string) string
}

Go 裏面比較噁心的是什麼呢?就是這裏的接口實現,從Java過來的看到這個肯定會比較懵逼。首先必須先生命一點,這裏的 Retriever struct 和 Retriever interface 不是必須取名要一致的,我純粹是爲了 這個 struct 要去實現 interface , 然後取名一樣的話,我知道我這個 struct 實現的是什麼 interface , 這裏的 interface 你可以換個名字,比如這樣看:

// package mooc
type Retriever struct {
	Contents string
}
func (r Retriever) Get(url string) string {
	return r.Contents
}
// package main
type InterfaceRetriever interface {
	Get(url string) string
}

現在你能看出來 Retriever struct 實現的是哪個 interface 嗎?看不出來的好吧?你要是覺得,實現的就是這個 InterfaceRetriever , 雖然的確是實現的是他,但是我們不能猜,我在改一下:

type Retriever interface {
	Get(url string) string
}

type InterfaceRetriever interface {
	Get(url string) string
}

現在你覺得,他實現的是哪一個?是不是看不出來?這怎麼可能看的出來實現的是哪一個呢?這就是我覺得 GO 裏面比較噁心的地方之一。我們現在來看一下,編輯器爲我們的引導:
Retriever interface:
1
InterfaceRetriever interface:
2
Retriever struct:
3

現在可以看到了,兩個interface 之間互通,Retriever struct 也是腳踏兩隻船。

可是如果這麼改之後:
4

這個時候,InterfaceRetriever interface 實現的是 Retriever interface 接口, Retriever struct 也是實現 Retriever interface 接口。這樣,就能說明問題了。 Go 裏面的接口實現看你實現的是那個方法裏面接口,而且是全部實現纔算你實現了接口,而且這裏面的優先原則是誰先被實現完,誰就是誰爸爸。

	var r Retriever
	r = mooc.Retriever{
		Contents: "this is mock interface",
	}
	fmt.Printf("%T %v \n" , r ,r)

	switch retriever := r.(type){
	case mooc.Retriever:
		fmt.Println("mooc Retriever: " , retriever.Contents)
	}

從這裏可以看到,在接口 Retriever 裏面, 也就是這裏的 r 裏面,是包含這個 接口類型和值的。

  • 接口變量自帶指針
  • 接口變量同樣採用值傳遞,幾乎不需要使用接口的指針
  • 指針接收者實現只能以指針方式使用;值接收者都可以
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章