t和* t之间的差异
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())
}
该代码可以很好地工作。但是,如果String
按如下所示更改方法,则会导致死循环。区别在于将*t
替换为t
。为什么?
func (t *TT) String() string { return fmt.Sprintf("%+v", t)
}
回答:
因为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
并产生运行时成本。
以上是 t和* t之间的差异 的全部内容, 来源链接: utcz.com/qa/406137.html