Golang對方法接收者變數的自動“取引用”和“解引用”
阿新 • • 發佈:2018-11-11
1. 寫在前面
文章的標題讀起來是有點拗口的,用一個簡單的示例大家便可以一目瞭然了,如下所示,st2
會被自動解引用從而呼叫StructTest
的printData
方法,而st3
會被自動取引用從而呼叫StructTest2
的printData
方法。
但很多時候,我們會發現這種自動的“取引用”或“解引用”不“奏效”了,尤其是遇到介面的時候,本文就是通過程式碼復現這種“不奏效”,並分析其中的原因。
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
,並定義了兩個實現該介面的類StructTest
和StructTest2
。在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部分的示例程式碼中,涉及到型別的匹配,那就是另外一個問題了,涉及到的是新的相應方法的生成。值型別的方法總會生成一個對應的指標型別方法,反之則不可以。