字符串方法中的指针接收器与值接收器
Go 中,String() 方法用于控制自定义的字符串表示类型。定义 String() 方法时,理解指针接收器和值接收器之间的区别至关重要。
考虑以下代码:
type TT struct { a int b float32 c string } func (t *TT) String() string { return fmt.Sprintf("%+v", *t) }
在此代码中, String( ) 方法有一个指针接收器,这意味着它对指向 TT 值的指针进行操作。调用 tt.String() 有效地调用 (*tt).String()。
现在,考虑将 String() 方法更改为以下内容:
func (t *TT) String() string { return fmt.Sprintf("%+v", t) }
此更改会删除指针接收者,使 String() 方法对 TT 类型的值进行操作。
为什么会导致死Loop?
fmt 包检查正在打印的值是否实现了 Stringer 接口(或具有 String() 方法)。如果是,它将调用该方法来获取字符串表示形式。然而,在这种情况下,我们有一个 String() 方法的指针接收器。
当我们调用 tt.String() 时,fmt 包传递一个 *TT 类型的值。但是,String() 方法需要 TT 类型的值。这种不匹配会导致 fmt 包再次调用 String() 方法,而 String() 方法又会被再次调用,依此类推,从而导致无限循环。
预防/保护
为了防止这种死循环,请确保 String() 方法的接收者类型与传递给 fmt 包的值的类型匹配。如果由于某种原因你需要使用相同的接收器类型,你可以使用 type 关键字创建一个新类型,并在调用 fmt.Sprintf 之前将值转换为新类型:
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
通过创建一个新的类型,我们从底层类型中删除所有方法,有效地打破循环并允许我们安全地调用 fmt.Sprintf。
以上是为什么字符串方法中的指针接收器会导致Go中的死循环?的详细内容。更多信息请关注PHP中文网其他相关文章!