理解 t 和 *t 之间的区别
在此代码片段中,我们有一个类型 TT 和一个实现 fmt 的 String 方法.Stringer 接口:
package main import "fmt" type TT struct { a int b float32 c string } func (t *TT) String() string { return fmt.Sprintf("%+v", *t) } func main() { tt := &TT{3, 4, "5"} fmt.Printf(tt.String()) }
这段代码之所以有效,是因为 fmt 包调用了 String方法来获取 TT 值的字符串表示形式。
但是,当修改 String 方法以采用非指针接收器时:
func (t *TT) String() string { return fmt.Sprintf("%+v", t) }
它会导致死循环。让我们解释一下原因:
调用 fmt.Sprintf("% v", t) 会将 *TT(指向 TT 的指针)值传递给 fmt 包。由于 TT.String 方法有一个指针接收器,因此 fmt 包不会在 *TT 类型的方法集中找到该方法。
将接收器更改为非指针类型意味着 fmt 包将在TT的方法集中找到String方法。但是,这会导致无限递归,因为被调用的方法与用于格式化值的方法相同。
为了避免此问题,可以使用 type 关键字创建一个新类型,从而有效地将传递给 fmt 包的值的接收者类型:
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
这有效是因为 type 关键字创建的新类型没有任何方法,因此 fmt 包不会尝试在新类型上调用 String 方法。
以上是为什么在使用“fmt.Sprintf”时将方法接收器从指针更改为非指针会导致死循环?的详细内容。更多信息请关注PHP中文网其他相关文章!