英文:
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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论