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中文网其他相关文章!