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类型的值传递TTfmt包。如果该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

回到顶部