因为
fmt程序包检查要打印的值是否具有
String()string方法(或换句话说:是否实现
fmt.Stringer接口),如果是,则将调用它以获取
string值的表示形式。
fmt软件包doc中对此进行了说明:
[…]如果操作数实现String()字符串方法,则将调用该方法将对象转换为字符串,然后根据动词的要求对其进行格式化(如果有)。
这里:
return fmt.Sprintf("%+v", *t)您正在将
*t类型的值传递
TT给
fmt包。如果该
TT.String()方法具有指针接收器,则该类型的方法集
TT
不包含 该
String()方法,因此
fmt程序包将不会调用它(仅
*TT包含它的方法集)。
如果更改接收到非指针类型,那么该类型的方法集
TT将包括
的
String()方法,所以
fmt包将调用,但这是我们目前正处在的方法,所以这是一个无休止的“间接递归”。
预防/保护
如果由于某种原因您确实需要使用与传递给
fmt包的值的类型相同的接收器类型,避免这种情况/避免这种情况发生的一种简单而通用的方法是
type使用关键字创建一个新类型,并使用type
传递的值的转换:
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t))}在Go Playground上尝试一下。
但是为什么这样做呢?因为
type关键字创建了一个新类型,并且该新类型将具有 零个 方法(它不会“继承”基础类型的方法)。
这会产生一些运行时开销吗?编号。引用自规范:类型声明:
特定规则适用于数字类型之间或字符串类型之间的(非恒定)转换。这些转换可能会更改的表示形式
x并产生运行时成本。
所有其他转换只会更改类型,而不会更改的表示形式x。



