1. 程式人生 > >Golang對方法接收者變數的自動“取引用”和“解引用”

Golang對方法接收者變數的自動“取引用”和“解引用”

1. 寫在前面

文章的標題讀起來是有點拗口的,用一個簡單的示例大家便可以一目瞭然了,如下所示,st2會被自動解引用從而呼叫StructTestprintData方法,而st3會被自動取引用從而呼叫StructTest2printData方法。
但很多時候,我們會發現這種自動的“取引用”或“解引用”不“奏效”了,尤其是遇到介面的時候,本文就是通過程式碼復現這種“不奏效”,並分析其中的原因。

package main

import "fmt"

type StructTest struct{
    data string
}

func (st StructTest) printData
() { fmt.Println(st.data) } type StructTest2 struct { data string } func (st *StructTest2) printData(){ fmt.Println(st.data) } func main() { st1 := StructTest{data: "seafooler"} st1.printData() st2 := &(StructTest{data: "seafooler"}) st2.printData() st3 := StructTest2{
data: "seafooler"} st3.printData() st4 := &(StructTest{data: "seafooler"}) st4.printData() }

2. 自動“取引用”或“解引用”遇到“介面”

2.1 現象

我們還是用程式碼舉例,如下所示,我們定義一個介面InterfaceTest,並定義了兩個實現該介面的類StructTestStructTest2。在main函式中,我們分別將實現類的變數的值或者引用賦值給介面變數,並通過介面變數來呼叫printData方法。發現程式中it3的賦值會出現編譯錯誤。

package
main import "fmt" type InterfaceTest interface { printData() } type StructTest struct { data string } func (st StructTest) printData() { fmt.Println(st.data) } type StructTest2 struct { data string } func (st *StructTest2) printData() { fmt.Println(st.data) } func main(){ st := StructTest{data: "seafooler"} var it1 InterfaceTest = st it1.printData() var it2 InterfaceTest = &st it2.printData() st2 := StructTest2{data: "seafooler"} var it3 InterfaceTest = st2 // 編譯出錯 it3.printData() var it4 InterfaceTest = &st2 it4.printData() }

2.2 原因

原因是因為,對於一個類來說,其值型別的方法會自動生成相應的指標型別的方法,而指標型別的方法不會自動生成相應的值型別的方法。在我們的程式示例中:

  • StructTest值型別的printData方法會自動生成一個func (st *StructTest) printData()方法,因此*StructTest也是符合InterfaceTest介面的。
  • 相反,StructTest2指標型別的printData方法不會自動生成一個func (st StructTest2) printData()方法,因此StructTest2不符合InterFaceTest介面,也就不能將st2賦值給it3

3. 總結

我們在談到變數的自動“取引用”和“解引用”時,往往是指在進行“方法呼叫”的時候。而第2部分的示例程式碼中,涉及到型別的匹配,那就是另外一個問題了,涉及到的是新的相應方法的生成。值型別的方法總會生成一個對應的指標型別方法,反之則不可以。