3 回答

TA貢獻1860條經驗 獲得超8個贊
XYZ 確實實現了 ABC。這與如何確定方法集有關(添加重點):
類型可以具有與其關聯的方法集。接口類型的方法集就是它的接口。任何其他類型 T 的方法集由接收者類型 T 聲明的所有方法組成。對應指針類型 *T 的方法集是接收者 *T 或 T 聲明的所有方法的集合(即還包含接收者類型 T 聲明的方法)。集 T)。
方法集決定接口是否實現:
接口類型指定稱為其接口的方法集。接口類型的變量可以存儲任何類型的值,其方法集是接口的任何超集。這樣的類型被稱為實現接口。
當調用 時*XYZ.a()
,Go 編譯器總是可以自動解引用指針來獲取值接收者。這樣做沒有任何缺點,因為接收者無法修改(就調用者而言)。
當且僅當該值是可尋址時,反邏輯才成立:
type T struct {}
func (*T) M()
func main() {
? ? var t T
? ? t.M() // ok; t is addressable and the compiler rewrites this to (*t).M()
? ? var m map[string]T
? ? m["x"].M() // error: cannot take the address of m["x"]
}

TA貢獻1812條經驗 獲得超5個贊
會出現錯誤,因為a(*main.XYZ)的類型沒有實現接口ABC
錯誤的。*main.XYZ
實現ABC
(否則abc = xyz
會在編譯時失敗,嘗試將方法重命名b
為c
例如),但該變量a
保存一個nil
指針(類型為*XYZ
)。由于該方法具有值接收器,因此要調用該方法,必須取消XYZ.a()
引用類型的指針值。*XYZ
但是nil
指針不指向任何內容,它不能被取消引用,嘗試這樣做會導致運行時恐慌,就像您所經歷的那樣。
如果您xyz
從一開始就使用非nil
指針進行初始化,那么它會起作用:
var xyz *XYZ = new(XYZ)
在Go Playground上嘗試一下。
另請注意,如果XYZ.a()
和XYZ.b()
會有指針接收器,那么如果xyz
是nil
:
func (xyz *XYZ) a() string {
return "XYZ"
}
func (xyz *XYZ) b() int {
return 123
}
func main() {
var xyz *XYZ
// ...
在Go Playground上嘗試一下。這樣做的原因是因為如果接收者是指針,則nil
不必取消引用指針即可調用帶有指針接收者的方法,因此不會發生運行時恐慌。當然,如果在方法中您引用XZY.aa
或XYZ.bb
字段,那將是運行時恐慌,但您當前的方法實現不會這樣做,所以它可以工作。

TA貢獻1811條經驗 獲得超5個贊
當我在值上調用方法時(不是指針,是實現接口的結構的方法,并且方法的接收者是指針)。Golang會創建一個新對象,并從原始struct值中復制值,然后,iface.data將指向新對象,現在,當我們將新對象的指針傳遞給方法時,它可以被修改,但是這個操作不會改變原始結構體值,這沒有任何用處,因此,當我們將結構體值分配給接口(指針接收者)時,Golang會發生錯誤
- 3 回答
- 0 關注
- 208 瀏覽
添加回答
舉報