英文:
Why doesn't fmt.Println use String() methods of members when called on a struct?
问题
原始代码中的类型foo
包含两个字段:b
和bb
,它们都是指向bar
类型的指针。在main
函数中,我们创建了一个foo
类型的实例f
,并初始化了它的字段b
和bb
。
在fmt.Println
语句中,我们打印了f
、f.b
和f.bb
的值。由于foo
类型的String
方法没有被定义,因此默认的打印格式是打印结构体的字段值。
对于f
的打印结果,{[0x176f44] 0x176f44}
表示f
的字段b
和bb
的内存地址。这是因为b
是一个指向bar
类型的指针切片,bb
是一个指向bar
类型的指针,它们的值是内存地址。
对于f.b
的打印结果,[bar]
表示f.b
切片中的第一个元素的默认打印格式,即指向bar
类型的指针的内存地址。
对于f.bb
的打印结果,bar
表示f.bb
指针指向的bar
类型的默认打印格式。
这种打印结果是由Go语言的默认打印格式决定的,它显示了字段的内存地址而不是字段的值。如果你想要打印字段的值而不是内存地址,你可以在foo
类型上定义一个String
方法,并在该方法中自定义打印格式。例如:
func (f foo) String() string {
return fmt.Sprintf("{[%v] %v} [%v] %v", f.b, f.bb, f.b[0], *f.bb)
}
这样,打印结果将会是{[bar] bar} [bar] bar
。
英文:
package main
import (
"fmt"
)
type bar struct {
}
func (b bar) String() string {
return "bar"
}
type foo struct {
b []*bar
bb *bar
}
func main() {
f := foo{b: []*bar{&bar{}}, bb:&bar{}}
fmt.Println(f, f.b, f.bb)
}
Why is the result
> {[0x176f44] 0x176f44} [bar] bar
and not
> {[bar] bar} [bar] bar
Are there any reasons behind it? It seems easy to implement and good for readability.
答案1
得分: 4
你的代码中有几个问题。你在bar
上定义了String
,但它是未导出的,你的字段也是未导出的。以下是修正后的代码:
type Bar struct {
}
func (b Bar) String() string {
return "bar"
}
type Foo struct {
B []Bar
BB Bar
}
func main() {
f := Foo{B: []Bar{Bar{}}, BB: Bar{}}
fmt.Println(f)
}
这段代码也可以使用*Bar
来实现。
英文:
You have several problems in your code. You define String
on bar
which is unexported, your fields are unexported as well. This works:
type Bar struct {
}
func (b Bar) String() string {
return "bar"
}
type foo struct {
B []Bar
BB Bar
}
func main() {
f := foo{B: []Bar{Bar{}}, BB: Bar{}}
fmt.Println(f)
}
Playground: https://play.golang.org/p/OhoIcB7cA3.
This would also work with *Bar
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论