英文:
Printing a Go type ignoring "String() string" method
问题
如果我在Go语言中有一个类型定义如下:
type myType ...
func (m myType) String() string { ... }
我如何使用默认表示(即不调用String()
方法)来打印该类型(使用各种fmt
函数)?我想要做的是像这样:
func (m myType) String() string {
// 一些任意的属性
if myType.isValid() {
// 格式化正确
} else {
// 会无限递归;希望使用默认表示
return fmt.Sprintf("无效的myType:%v", m)
}
}
英文:
If I have a type in go like this:
type myType ...
func (m myType) String() string { ... }
how can I print (using the various fmt
functions) this type using the default representation (that is, instead of having String()
called)? What I'd like to do is something like this:
func (m myType) String() string {
// some arbitrary property
if myType.isValid() {
// format properly
} else {
// will recurse infinitely; would like default
// representation instead
return fmt.Sprintf("invalid myType: %v", m)
}
}
答案1
得分: 6
fmt.Stringer
是默认的格式,当你使用%v
时会调用它。如果你想要Go语法的格式,可以使用%#v
。
另外,你也可以完全绕过fmt
中的反射,按照你的需求格式化输出。
func (m myType) String() string {
return fmt.Sprintf("Field: %s", m.Value)
}
如果myType
的底层类型是数字、字符串或其他简单类型,那么在打印时将其转换为底层类型:
func (m mType) String() string {
return fmt.Sprint(int(m))
}
英文:
fmt.Stringer
is the default format, which is called when you use %v
. If you want the Go syntax, use %#v
.
Alternatively, you can bypass the reflection in fmt
altogether, and format your output as you see fit.
func (m myType) String() string {
return fmt.Sprintf("{Field: %s}", m.Value)
}
If the underlying type of myType is a number, string or other simple type, then convert to the underlying type when printing:
func (m mType) String() string {
return fmt.Sprint(int(m))
}
答案2
得分: 4
使用%#v
代替%v
。
这样不会调用String()
方法,但如果你实现了GoString()
方法,它会调用GoString()
方法。
英文:
Use %#v
instead of %v
That will not invoke String(). - but it will invoke GoString() if you implement it.
答案3
得分: 2
使用%#v
格式是不正确的答案,如果你想要让底层类型的String
方法工作,或者你的类型是一个类型别名。
如Effective Go中所解释的,只需将其转换回表示的类型即可:
type Foo int
func (f Foo) String() string {
if f == 0 {
return "foo"
}
return fmt.Sprintf("%v", int(f)) // 注意
}
func main() {
fmt.Println(Foo(0))
fmt.Println(Foo(42))
}
**编辑:**正如其他人在评论中指出的,如果你的类型是一个结构体,除了将其转换为具有相同字段的匿名结构体类型,使用%#v
格式似乎是唯一的方法。
英文:
Using %#v
format is not the correct answer if you want to get your underlying type's String
to work or your type is a type alias.
As is explained in Effective Go, just convert it back to the type it represents:
type Foo int
func (f Foo) String() string {
if f == 0 {
return "foo"
}
return fmt.Sprintf("%v", int(f)) // N.B.
}
func main() {
fmt.Println(Foo(0))
fmt.Println(Foo(42))
}
EDIT: As others have pointed out in the comments, if your type is a struct, using %#v
format seems like the only way besides converting it to an anonymous struct type with same fields.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论