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