string - t和*t的区别

标签 string pointers go methods stack-overflow

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 package 检查打印的值是否有 String() string 方法(或者换句话说:如果它实现了 fmt.Stringer 接口(interface)),如果有,它将被调用以获取 >string 值的表示。

这在 fmt 包文档中有记录:

[...] If an operand implements method String() string, that method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).

这里:

return fmt.Sprintf("%+v", *t)

您正在将 TT 类型的值 *t 传递给 fmt 包。如果 TT.String() 方法有一个指针接收器,那么 method set TT 类型的不包含 String() 方法,因此fmt 包不会调用它(只有 *TT 的方法集包含它。

如果将接收者改为非指针类型,那么TT类型的方法集将包含String()方法,所以 fmt 包会调用它,但这是我们目前使用的方法,所以这是一个无休止的“间接递归”。

预防/保护

如果出于某种原因您确实需要使用与传递给 fmt 包的值类型相同的接收器类型,那么避免这种情况/防止这种情况发生的一种简单而常用的方法是使用 type 创建一个新类型关键字,并使用类型 conversion关于传递的值:

func (t TT) String() string {
    type TT2 TT
    return fmt.Sprintf("%+v", TT2(t))
}

Go Playground 上试试这个.

但是为什么这行得通呢?因为 type 关键字创建了一个新类型,并且新类型将具有 方法(它不会“继承”基础类型的方法)。

这会产生一些运行时开销吗?编号引用自Spec: Type declarations :

Specific rules apply to (non-constant) conversions between numeric types or to and from a string type. These conversions may change the representation of x and incur a run-time cost. All other conversions only change the type but not the representation of x.

在这里阅读更多相关信息:Does convertion between alias types in Go create copies?

关于string - t和*t的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43065856/

相关文章:

regex - Concat 正则表达式与常量声明中的字符串作为 oneliner

string - 多文本比较算法

c# - int 到 float 指针

检查数组中相同的数字及其值

c++ - 帮助我理解这个 URL 解码器 :

go - 避免在 golang 上调试信息

c - 如何将 char(ASCII 字符)转换为保存在 C 字符串变量中的科学计数法

android - 使用 TextWatcher 在 EditText 中设置最大字数限制

go - 在多个goroutine之间共享的Golang结构中,非共享成员是否需要互斥保护?

concurrency - Enque 和 deque 使 channel 死锁