使用Go 介面時,當實作宣告介面傳回類型的介面方法時,可能會發生錯誤透過具體類型。出現此錯誤的原因是該方法的實作不會直接傳回介面類型,而是傳回實作該介面的特定類型。
考慮以下範例:
<code class="go">package main import "fmt" type Foo struct { val string } func (f *Foo) String() string { return f.val } type StringerGetter interface { GetStringer() fmt.Stringer } type Bar struct{} func (b *Bar) GetStringer() *Foo { return &Foo{"foo"} } func Printer(s StringerGetter) { fmt.Println(s.GetStringer()) } func main() { f := Bar{} Printer(&f) }</code>
這裡, Printer 函數需要一個StringerGetter 接口,該介面有一個傳回fmt.Stringer 的GetStringer 方法,而Bar 類型的GetStringer 方法則傳回一個實作fmt .Stringer 介面的具體類型Foo。這會導致錯誤:
prog.go:29: cannot use &f (type *Bar) as type StringerGetter in argument to Printer: *Bar does not implement StringerGetter (wrong type for GetStringer method) had GetStringer() *Foo want GetStringer() fmt.Stringer
這個問題的解決方案在於使介面的方法與預期的介面類型相符。在這種情況下,GetStringer 方法應該傳回fmt.Stringer 而不是具體類型:
<code class="go">func (b *Bar) GetStringer() fmt.Stringer { return &Foo{"foo"} }</code>
或者,可以建立一個包裝類型來實現所需的介面並委託給具體類型,如以下技術:
型嵌入與委託:
<code class="go">type MyBar struct{ Bar } func (b *MyBar) GetStringer() fmt.Stringer { return b.Bar.GetStringer() }</code>
類型包裝:
<code class="go">type MyBar Bar func (b *MyBar) GetStringer() fmt.Stringer { return &Foo{"foo"} }</code>
這些技術允許與具體類型無縫連接,而無需直接修改它們。透過包裝或嵌入具體類型,可以建立符合所需介面契約的自訂類型。
以上是當具體類型實作傳回具體類型而不是介面方法中預期的介面類型時,為什麼 Go 會拋出錯誤?的詳細內容。更多資訊請關注PHP中文網其他相關文章!