Go 嵌入類型中意外的String() 方法行為
在Go 中使用嵌入類型時,嵌入類型的字段和方法是擁抱型有效地繼承了這一點。這可能會導致意外行為,尤其是在處理自訂 String() 方法時。
考慮以下範例:
type Engineer struct { Person TaxPayer Specialization string } type Person struct { Name string Age int } func (p Person) String() string { return fmt.Sprintf("name: %s, age: %d", p.Name, p.Age) } type TaxPayer struct { TaxBracket int } func (t TaxPayer) String() string { return fmt.Sprintf("%d", t.TaxBracket) }
在此程式碼中,Engineer 類型嵌入了 Person 和 TaxPayer 類型,它們定義自己的 String() 方法來格式化對應的資料。但是,如果我們實例化一個Engineer 物件並呼叫fmt.Println(engineer),則輸出並不符合預期:
{name: John Doe, age: 35 3 Construction}
此輸出表示正在呼叫Engineer.String() 方法,但TaxPayer.String () 方法也對結果有貢獻。這是因為 String() 方法在嵌入時會提升為 Engineer 類型,而 Person.String() 和 TaxPayer.String() 方法都可以呼叫。
為了澄清這一點,請考慮以下內容場景:
fmt.Println(engineer.String()) // Compile error: ambiguous selector engineer.String
在這種情況下,編譯器會引發錯誤,因為工程師有多個提升的String() 方法,導致選擇器不明確。然而,fmt.Println(engineer) 會成功,因為編譯器會根據其欄位自動選擇 Engineer 的預設格式。
造成這種明顯差異的原因是 fmt.Println() 函數本質上委託了字串轉換到 fmt 套件。當它遇到實作 fmt.Stringer 介面(定義 String() 方法)的值時,它會呼叫該方法來取得字串表示形式。
在我們的範例中,因為 Person.String() 和TaxPayer.String() 存在,兩者均未晉升為工程師,並使用預設格式。然而,在 fmt.Println(engineer.String()) 的情況下,編譯器會遇到不明確的選擇器並引發錯誤。
總之,當多個嵌入類型定義了此類方法。了解嵌入和方法提升的機制非常重要,以避免潛在的混亂並確保所需的輸出。
以上是為什麼 Go 的'fmt.Println”使用嵌入類型和多個'String()”方法會產生意外的輸出?的詳細內容。更多資訊請關注PHP中文網其他相關文章!