3 回答

TA貢獻(xiàn)1860條經(jīng)驗(yàn) 獲得超8個(gè)贊
XYZ 確實(shí)實(shí)現(xiàn)了 ABC。這與如何確定方法集有關(guān)(添加重點(diǎn)):
類型可以具有與其關(guān)聯(lián)的方法集。接口類型的方法集就是它的接口。任何其他類型 T 的方法集由接收者類型 T 聲明的所有方法組成。對(duì)應(yīng)指針類型 *T 的方法集是接收者 *T 或 T 聲明的所有方法的集合(即還包含接收者類型 T 聲明的方法)。集 T)。
方法集決定接口是否實(shí)現(xiàn):
接口類型指定稱為其接口的方法集。接口類型的變量可以存儲(chǔ)任何類型的值,其方法集是接口的任何超集。這樣的類型被稱為實(shí)現(xiàn)接口。
當(dāng)調(diào)用 時(shí)*XYZ.a()
,Go 編譯器總是可以自動(dòng)解引用指針來獲取值接收者。這樣做沒有任何缺點(diǎn),因?yàn)榻邮照邿o法修改(就調(diào)用者而言)。
當(dāng)且僅當(dāng)該值是可尋址時(shí),反邏輯才成立:
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貢獻(xiàn)1812條經(jīng)驗(yàn) 獲得超5個(gè)贊
會(huì)出現(xiàn)錯(cuò)誤,因?yàn)閍(*main.XYZ)的類型沒有實(shí)現(xiàn)接口ABC
錯(cuò)誤的。*main.XYZ
實(shí)現(xiàn)ABC
(否則abc = xyz
會(huì)在編譯時(shí)失敗,嘗試將方法重命名b
為c
例如),但該變量a
保存一個(gè)nil
指針(類型為*XYZ
)。由于該方法具有值接收器,因此要調(diào)用該方法,必須取消XYZ.a()
引用類型的指針值。*XYZ
但是nil
指針不指向任何內(nèi)容,它不能被取消引用,嘗試這樣做會(huì)導(dǎo)致運(yùn)行時(shí)恐慌,就像您所經(jīng)歷的那樣。
如果您xyz
從一開始就使用非nil
指針進(jìn)行初始化,那么它會(huì)起作用:
var xyz *XYZ = new(XYZ)
在Go Playground上嘗試一下。
另請(qǐng)注意,如果XYZ.a()
和XYZ.b()
會(huì)有指針接收器,那么如果xyz
是nil
:
func (xyz *XYZ) a() string {
return "XYZ"
}
func (xyz *XYZ) b() int {
return 123
}
func main() {
var xyz *XYZ
// ...
在Go Playground上嘗試一下。這樣做的原因是因?yàn)槿绻邮照呤侵羔槪瑒tnil
不必取消引用指針即可調(diào)用帶有指針接收者的方法,因此不會(huì)發(fā)生運(yùn)行時(shí)恐慌。當(dāng)然,如果在方法中您引用XZY.aa
或XYZ.bb
字段,那將是運(yùn)行時(shí)恐慌,但您當(dāng)前的方法實(shí)現(xiàn)不會(huì)這樣做,所以它可以工作。

TA貢獻(xiàn)1811條經(jīng)驗(yàn) 獲得超5個(gè)贊
當(dāng)我在值上調(diào)用方法時(shí)(不是指針,是實(shí)現(xiàn)接口的結(jié)構(gòu)的方法,并且方法的接收者是指針)。Golang會(huì)創(chuàng)建一個(gè)新對(duì)象,并從原始struct值中復(fù)制值,然后,iface.data將指向新對(duì)象,現(xiàn)在,當(dāng)我們將新對(duì)象的指針傳遞給方法時(shí),它可以被修改,但是這個(gè)操作不會(huì)改變?cè)冀Y(jié)構(gòu)體值,這沒有任何用處,因此,當(dāng)我們將結(jié)構(gòu)體值分配給接口(指針接收者)時(shí),Golang會(huì)發(fā)生錯(cuò)誤
- 3 回答
- 0 關(guān)注
- 206 瀏覽
添加回答
舉報(bào)