Stringer 接口與Println 的混淆:理解基於值與基於指針的對象
問題:
在物件實作了Stringer介面的場景下,為什麼不如果物件是基於值的,那麼使用fmt.Println 時會呼叫物件的 String 方法嗎?
程式碼範例:
考慮以下 Go 程式碼:
type Car struct { year int make string } func (c *Car) String() string { return fmt.Sprintf("{make:%s, year:%d}", c.make, c.year) } func main() { myCar := Car{year: 1996, make: "Toyota"} fmt.Println(myCar) }
當 myCar 是指標時,String 方法會按預期呼叫。但是,當 myCar 是一個值時,就會使用預設的 Go 格式。
答案:
此行為的原因在於 Go 介面的工作方式。當您指定實作介面的類型(在本例中為 Stringer)時,Go 會期望該類型是介面的確切類型。當您將Car類型的值傳遞給fmt.Println時,它會隱式轉換為interface{},並且interface{}類型系統中沒有Car類型。相反,它是 *Car 類型(指向 Car 的指標)。
fmt.Println 函數使用類型開關來決定如何根據其類型列印值。對於 Stringer 接口,它檢查該值是否實作 String 方法。由於 Car(基於值)不實作 String,因此使用預設格式。但是,當您明確呼叫 myCar.String() 時,編譯器會自動將其轉換為 (&myCar).String(),它具有正確的 *Car 類型並呼叫所需的格式化方法。
以確保無論其類型如何,物件都會根據需要進行格式化,您有兩個選擇:
以上是為什麼 fmt.Println 在傳遞基於值的物件時不呼叫我的 Stringer 介面的 String 方法?的詳細內容。更多資訊請關注PHP中文網其他相關文章!