首頁 >後端開發 >Golang >當嵌入類型具有衝突的'String()”方法時,為什麼'fmt.Println()”與 Go 中的嵌入類型的行為不同?

當嵌入類型具有衝突的'String()”方法時,為什麼'fmt.Println()”與 Go 中的嵌入類型的行為不同?

Patricia Arquette
Patricia Arquette原創
2024-11-30 07:28:11313瀏覽

Why does `fmt.Println()` behave differently with embedded types in Go when the embedded types have conflicting `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)
}

func main() {
    engineer := Engineer{
        Person: Person{
            Name: "John Doe",
            Age:  35,
        },
        TaxPayer: TaxPayer{3},
        Specialization: "Construction",
    }
    fmt.Println(engineer)
}

此程式碼的輸出是:

{name: John Doe, age: 35 3 Construction}

但是,如果刪除Person.String(),輸出會變成:

3

並且如果TaxPayer.String()也被刪除,輸出改為:

{{John Doe 35} {3} Construction}

最初,似乎 Engineer 結構必須有一個隱式 String() 方法。然而,事實並非如此。

嵌入類型中的 String() 方法

當類型嵌入到結構體中時,可以透過以下方式存取它們的欄位和方法:嵌入類型。如果多個嵌入類型定義同名的方法(例如 String()),則這種方法的「提升」可能會導致歧義。

在給定的程式碼範例中,因為 Person 和 TaxPayer 都有一個 String()方法,將這些方法提升到 Engineer 類型會導致歧義。這就是為什麼 Engineer.String() 會導致編譯錯誤。

為什麼使用fmt.Println() 時不會出現歧義錯誤

儘管Engineer 的方法集中有歧義、 fmt.Println(engineer) 不會導致編譯錯誤。這是因為 fmt.Println() 呼叫 fmt.Fprint(os.Stdout, Engineer)。

fmt.Fprint() 檢查傳遞的值是否實作 fmt.Stringer 接口,其中包含 String() 方法。如果是,則使用 String() 產生值的字串表示形式。

在這種情況下,由於 Person 和 TaxPayer 都沒有實作 fmt.Stringer,因此使用預設格式(結構欄位)。這會導致我們在呼叫 fmt.Println(engineer) 時看到的輸出。

結論

理解嵌入類型的行為及其方法的推廣至關重要在圍棋中。當多個嵌入類型定義同名的方法時,可能會導致歧義,從而導致編譯錯誤。但是,使用 fmt.Println() 時,如果傳遞的值未實作 fmt.Stringer,則使用預設格式。

以上是當嵌入類型具有衝突的'String()”方法時,為什麼'fmt.Println()”與 Go 中的嵌入類型的行為不同?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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