首頁 > 後端開發 > Golang > 主體

X 沒有實作 Y(...方法有指標接收器)

WBOY
發布: 2024-02-12 23:27:08
轉載
866 人瀏覽過

X 没有实现 Y(...方法有一个指针接收器)

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的方法集不包含內嵌mytypestring()方法,只有*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中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!