首頁  >  文章  >  後端開發  >  為什麼 Go 的'fmt.Println”使用嵌入類型和多個'String()”方法會產生意外的輸出?

為什麼 Go 的'fmt.Println”使用嵌入類型和多個'String()”方法會產生意外的輸出?

DDD
DDD原創
2024-11-21 20:23:181002瀏覽

Why Does Go's `fmt.Println` Produce Unexpected Output with Embedded Types and Multiple `String()` Methods?

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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn