在Go语言中,为什么在将类型转换为字符串时不使用stringer接口?

huangapple go评论105阅读模式
英文:

In Go, why isn't the stringer interface used when casting to string?

问题

package main

type foo struct {
    bar string
    baz string
}

func (f foo) String() string {
    return f.bar + " " + f.baz
}

func main() {
    f := foo{"hello", "world"}
    v := string(f)
}

这段代码输出 main.go:14: cannot convert f (type foo) to type string

所以看起来将某个类型转换为字符串时并不会考虑到 Stringer 接口。我猜测这是因为类型转换是在比 Stringer 接口更低层次上实现的,很难将两者混合使用,但我不确定。有人能解释一下吗?

另外,既然这种转换不可能,那么在这种情况下,将结构体转换为字符串的惯用方式是什么?我是直接调用 .String() 方法,还是使用 fmt.Sprintf("%s", f),还是其他什么方法?

英文:
package main

type foo struct {
    bar string
	baz string
}

func (f foo) String() string {
    return f.bar + " " + f.baz
}

func main() {
	f := foo{"hello", "world"}
	v := string(f)
}

This outputs main.go:14: cannot convert f (type foo) to type string.

So it would seem that casting something to a string does not look at the stinger interface. My guess is that this is because casting is implemented on a lower level than the stringer interface and it's impossible/hard to mix the two, but I'm not sure. Can anyone shed any light on this?

Also, since this is not possible, what would be idiomatic way to convert my struct to a string in this case? Do I just call .String() myself, or fmt.Sprintf("%s", f), or something else?

答案1

得分: 6

在Go语言中,没有"casting"的概念,而是使用类型转换(Conversion)和类型断言(Type assertion)。

你所做的T(Expression)是一种类型转换,它有严格的规则来确定何时可以使用以及结果是什么。

对于转换为字符串类型和从字符串类型转换,有特定的规则。因此,你无法通过类型转换来实现你想要的效果。

最简单和首选的方法是直接调用方法:

v := f.String()

如果你的struct已经实现了Stringer接口,那么使用fmt.Sprintf()只会增加不必要的开销和复杂性。但如果你不能保证这一点,那么使用fmt.Sprintf()是一种通用的方式。

你可能会问为什么?

在规范级别上,类型转换表达式并没有定义为自定义/用户制作的函数或方法的结果。与error接口不同,Stringer接口(type Stringer interface{String() string})甚至不是内置类型。

尽管Stringer不是内置类型,但它仍然存在于一些包中(例如fmt.Stringer),并且被各种方法或函数(例如fmt.Printf()及其相关函数)检查。

英文:

There is no casting in Go, there is type Conversion and Type assertion.

What you're doing (T(Expression)) is a conversion and it has strict rules when it can be used and what the result will be.

There are specific rules applied to Conversions to and from a string type. So what you want cannot be achieved with type conversion.

The simplest and preferred way would be to call the method yourself:

v := f.String()

fmt.Sprintf() would be just an unnecessary overhead and complication if your struct already implements Stringer. But if you don't have guarantee for this, then yes, fmt.Sprintf() would be the general way.

You could ask why?

In the specification level the type conversion expression is not defined as the result of a custom/user made function or method. The Stringer interface (type Stringer interface{String() string}) is not even a built-in type in contrast to the error interface.

But despite the fact that Stringer is not a built-in type, it is still present in some packages (for example in fmt.Stringer) and is checked by various methods or functions (e.g. fmt.Printf() and relatives).

huangapple
  • 本文由 发表于 2015年3月30日 17:34:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/29342776.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定