php小編小新將在這篇文章中探討一個關於X未能實現Y的問題。在這個問題中,我們使用了一個指標接收器的方法。透過這個方法,我們可以更好地理解為什麼X無法實現Y,並且找到解決這個問題的方法。在接下來的內容中,我們將詳細討論這個問題,並提供一些解決方案。
已經有幾個關於「X 沒有實作Y(...方法有指標接收器)」問題的問答,但對我來說,他們似乎在談論不同的事情,並且不適用於我的具體情況。
因此,我沒有將問題變得非常具體,而是將其變得廣泛和抽象 - 似乎有幾種不同的情況可能會導致此錯誤發生,有人可以總結一下嗎?
即如何避免該問題,如果發生,有哪些可能性?謝謝。
當您嘗試將具體類型指派或傳遞(或轉換)為介面類型時,會出現此編譯時錯誤;並且類型本身並不實作該接口,僅實作一個指向該類型的指標。
簡短摘要:對變數的賦值如果所指派的值實作了所指派的接口,則介面類型有效。如果它的方法集是介面的超集,它就會實現它。指標類型的方法集包括具有指標和非指標接收器的方法。非指標類型的方法集僅包括具有非指標接收器的方法。
讓我們來看一個例子:
type stringer interface { string() string } type mytype struct { value string } func (m *mytype) string() string { return m.value }
stringer
介面類型只有一個方法:string()
。儲存在介面值 stringer
中的任何值都必須具有此方法。我們也建立了一個 mytype
,並建立了一個有指標接收器的方法 mytype.string()
。這表示 string()
方法位於 *mytype
類型的 方法集 中,但不在 mytype
中。
當我們嘗試將 mytype
的值指派給 stringer
類型的變數時,我們收到以下錯誤:
m := mytype{value: "something"} var s stringer s = m // cannot use m (type mytype) as type stringer in assignment: // mytype does not implement stringer (string method has pointer receiver)
但如果我們嘗試將 *mytype
類型的值指派給 stringer
,則一切正常:
s = &m fmt.println(s)
我們得到了預期的結果(在 go playground 上嘗試):
something
因此獲得此編譯時錯誤的要求:
解決問題的可能性:
當使用結構和嵌入時,通常不是「你」實作介面(提供方法實作),而是嵌入 struct
中的類型。就像這個例子:
type mytype2 struct { mytype } m := mytype{value: "something"} m2 := mytype2{mytype: m} var s stringer s = m2 // compile-time error again
再次編譯時出錯,因為mytype2
的方法集不包含內嵌mytype
的string()
方法,只有*mytype2
的方法集,所以下面的方法有效(在去遊樂場):
var s stringer s = &m2
如果我們嵌入*mytype
並且只使用非指標 mytype2
,我們也可以使其工作(在去遊樂場 ):
type mytype2 struct { *mytype } m := mytype{value: "something"} m2 := mytype2{mytype: &m} var s stringer s = m2
此外,無論我們嵌入什麼(mytype
或*mytype
),如果我們使用指標*mytype2
,它總是可以工作(在去遊樂場):
type mytype2 struct { *mytype } m := mytype{value: "something"} m2 := mytype2{mytype: &m} var s stringer s = &m2
規範中的相關部分(來自結構類型部分):
给定一个结构体类型 s
和一个名为 t
的类型,提升的方法包含在该结构体的方法集中,如下所示:
s
包含匿名字段 t
,则 s
和 *s
的方法集均包含接收者为 t
的提升方法。 *s
的方法集还包括接收者 *t
的提升方法。s
包含匿名字段 *t
,则 s
和 *s
的方法集都包含接收者为 t
或 *t
的提升方法。换句话说:如果我们嵌入一个非指针类型,非指针嵌入器的方法集只能获取具有非指针接收器的方法(来自嵌入类型)。
如果我们嵌入一个指针类型,非指针嵌入器的方法集将获取具有指针和非指针接收器的方法(来自嵌入类型)。
如果我们使用指向嵌入器的指针值,则无论嵌入类型是否是指针,指向嵌入器的指针的方法集始终都会获取具有指针和非指针接收器的方法(从嵌入类型)。
注意:
有一个非常相似的情况,即当您有一个包含 mytype
值的接口值时,并且您尝试 类型断言 另一个接口值,stringer
。在这种情况下,由于上述原因,断言将不成立,但我们会得到一个略有不同的运行时错误:
m := mytype{value: "something"} var i interface{} = m fmt.println(i.(stringer))
运行时恐慌(在 go playground 上尝试一下):
panic: interface conversion: main.mytype is not main.stringer: missing method string
尝试转换而不是类型断言,我们得到了我们正在讨论的编译时错误:
m := MyType{value: "something"} fmt.Println(Stringer(m))
以上是X 沒有實作 Y(...方法有指標接收器)的詳細內容。更多資訊請關注PHP中文網其他相關文章!