为什么我的Stringer接口方法没有被调用?使用fmt.Println时

编程入门 行业动态 更新时间:2024-10-25 20:25:14
本文介绍了为什么我的Stringer接口方法没有被调用?使用fmt.Println时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

假设我有以下代码:

package main import "fmt" 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) }

当我调用fmt.Println(myCar)且有问题的对象是指针时,我的String()方法将被正确调用.但是,如果该对象是一个值,则使用Go内置的默认格式对我的输出进行格式化,而不会调用格式化该对象的代码.

When I call fmt.Println(myCar) and the object in question is a pointer, my String() method gets called properly. If, however the object is a value, my output is formatted using the default formatting built into Go and my code to format the said object is not called.

有趣的是,无论哪种情况,如果我手动调用myCar.String(),无论我的对象是指针还是值,它都能正常工作.

The interesting thing is in either case if I call myCar.String() manually it works properly whether my object is either a pointer or value.

与Println一起使用时,无论对象是基于值还是基于指针,如何以我想要的方式格式化对象?

How can I get my object formatted the way I want no matter if the object is value-based or pointer-based when used with Println?

我不想为String使用value方法,因为那样就意味着每次调用它时,都会复制对象,从而产生不合理的接缝.而且我也不想总是手动调用.String(),因为我正试图让鸭子键入系统来工作.

I don't want to use a value method for String because then that means every time it's invoked the object is copied which seams unreasonable. And I don't want to have to always manually called .String() either because I'm trying to let the duck-typing system do it's work.

推荐答案

调用函数fmt.Println时,myCar被隐式转换为类型为interface{}的值,如您从函数签名中所见.然后,来自fmt包的代码会执行类型切换,以弄清楚如何打印此值,如下所示:

When calling fmt.Println, myCar is implicitly converted to a value of type interface{} as you can see from the function signature. The code from the fmt package then does a type switch to figure out how to print this value, looking something like this:

switch v := v.(type) { case string: os.Stdout.WriteString(v) case fmt.Stringer: os.Stdout.WriteString(v.String()) // ... }

但是,由于Car没有实现String(如在*Car上定义的),因此fmt.Stringer情况失败.手动调用String是有效的,因为编译器发现String需要一个*Car,从而自动将myCar.String()转换为(&myCar).String().对于任何有关接口的内容,您都必须手动进行.因此,您要么必须在Car上实现String,要么总是将指针传递给fmt.Println:

However, the fmt.Stringer case fails because Car doesn't implement String (as it is defined on *Car). Calling String manually works because the compiler sees that String needs a *Car and thus automatically converts myCar.String() to (&myCar).String(). For anything regarding interfaces, you have to do it manually. So you either have to implement String on Car or always pass a pointer to fmt.Println:

fmt.Println(&myCar)

更多推荐

为什么我的Stringer接口方法没有被调用?使用fmt.Println时

本文发布于:2023-11-03 15:58:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1555512.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:接口   方法   Stringer   fmt   Println

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!