【Go學習筆記13】介面和實現

zhongzhong05發表於2017-12-10

介面

在go語言中,也可以定義介面型別。我們都知道,在物件導向的程式語言中,介面是實現多肽的必要條件。我們可以通過介面來接收不同的實現。go語言中通過interface關鍵字來定義介面。

//定義一個Reader介面
type Reader interface{
	//定義介面方法
	read()
}
複製程式碼

上面定義了一個介面,那麼如何來實現介面呢?在go語言中,可以在自定義的型別中通過方法來實現介面。我們來一個例子:

package main

import (
	"fmt"
)

//定義一個Reader介面
type Reader interface{
	//定義介面方法
	read()
}

//自定義型別
type FileReader struct{
	fileName string
	fileSize int
}

//實現Reader介面
func (fr FileReader) read(){
	fmt.Println("來自FileReader實現。。")
}


func main(){
	//使用介面型別接收
	var reader Reader = FileReader{fileName:"data.txt",fileSize:1024}
	//呼叫介面方法
	reader.read()
	fmt.Println("mian函式執行完成")
}
//來自FileReader實現。。
//mian函式執行完成
複製程式碼

從上面的程式碼我們可以看到,go語言中實現介面的方式比較特別,它是通過實現對應介面的方法來達到實現介面的目的,從而可以使用介面型別來接收具體的實現型別,也就具有了多肽特性。

再來看一個複雜點的例子:

package main

import (
	"fmt"
)

//定義一個Reader介面
type Reader interface{
	//定義介面方法
	read()
}

//自定義型別
type FileReader struct{
	fileName string
	fileSize int
}

type JsonReader struct{
	total int
}

//實現Reader介面的方法
func (fr FileReader) read(){
	//修改fileName
	fr.fileName = "new name";
	fmt.Println("來自FileReader實現。。")
}

//實現Reader介面的方法,使用JsonReader指標作為接收者
func (jr *JsonReader) read(){
	jr.total = 101
	fmt.Println("來自JsonReader的實現")
}

func startReader(reader Reader){
	fmt.Println("開始執行read方法")
	reader.read()
	fmt.Println("read方法執行結束")
}

func main(){
	fr := FileReader{fileName:"data.txt",fileSize:1024}
  //注意這裡,使用的是指標
	jr := JsonReader{total:100}

	startReader(fr)
	fmt.Println("fileName=",fr.fileName)

	startReader(&jr)	
	fmt.Println("total=",jr.total)
	fmt.Println("mian函式執行完成")
}
//開始執行read方法
//來自FileReader實現。。
//read方法執行結束
//fileName= data.txt
//開始執行read方法
//來自JsonReader的實現
//read方法執行結束
//total= 101
//mian函式執行完成
複製程式碼

上面的程式碼,新增加了JsonReader型別,它也實現了Reader介面。但是有一點不同,JsonReadr在實現Reader介面的時候,使用的是指標作為方法的接收者。而FileReader是使用值作為方法的接收者。那麼這兩種方式有什麼不同呢?

通過上面的程式碼可以看出,在實現的read方法內部,修改實現的屬性,使用值做為接收者的時候,屬性修改不成功,這是因為值傳遞的是一個副本,對副本的修改不會影響值的本身。而使用指標作為接收者的時候,對屬性的修改都會體現在對應的物件上面。

startReader函式的引數型別是Reader型別,並不是指標,那麼為什麼在startReader(jr) 的時候,將指標型別傳遞給它,函式也能正常執行呢?

在go語言中:

如果使用指標接收者來實現一個介面,那麼只有指向那個型別的指標才能夠實現對應的介面。 如果使用值接收者來實現介面,那麼那個型別的值和指標都可以實現對應的介面。

上面的兩句是什麼意思呢,對比上面的程式碼來說。 startReader(fr)可以改成startReader(&fr),程式同樣可以正確執行,但是結果一樣。

startReader(&jr)不能改成startReader(jr),否者編譯會報錯。

相關文章