首页  >  文章  >  后端开发  >  为什么在使用“fmt.Sprintf”时将方法接收器从指针更改为非指针会导致死循环?

为什么在使用“fmt.Sprintf”时将方法接收器从指针更改为非指针会导致死循环?

DDD
DDD原创
2024-11-16 01:10:02151浏览

Why Does Changing a Method Receiver from Pointer to Non-Pointer Lead to a Dead Loop When Using `fmt.Sprintf`?

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

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn