打印一个Go类型,忽略”String() string”方法。

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

Printing a Go type ignoring "String() string" method

问题

如果我在Go语言中有一个类型定义如下:

  1. type myType ...
  2. func (m myType) String() string { ... }

我如何使用默认表示(即不调用String()方法)来打印该类型(使用各种fmt函数)?我想要做的是像这样:

  1. func (m myType) String() string {
  2. // 一些任意的属性
  3. if myType.isValid() {
  4. // 格式化正确
  5. } else {
  6. // 会无限递归;希望使用默认表示
  7. return fmt.Sprintf("无效的myType:%v", m)
  8. }
  9. }
英文:

If I have a type in go like this:

  1. type myType ...
  2. 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:

  1. func (m myType) String() string {
  2. // some arbitrary property
  3. if myType.isValid() {
  4. // format properly
  5. } else {
  6. // will recurse infinitely; would like default
  7. // representation instead
  8. return fmt.Sprintf("invalid myType: %v", m)
  9. }
  10. }

答案1

得分: 6

fmt.Stringer是默认的格式,当你使用%v时会调用它。如果你想要Go语法的格式,可以使用%#v

另外,你也可以完全绕过fmt中的反射,按照你的需求格式化输出。

  1. func (m myType) String() string {
  2. return fmt.Sprintf("Field: %s", m.Value)
  3. }

如果myType的底层类型是数字、字符串或其他简单类型,那么在打印时将其转换为底层类型:

  1. func (m mType) String() string {
  2. return fmt.Sprint(int(m))
  3. }
英文:

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.

  1. func (m myType) String() string {
  2. return fmt.Sprintf("{Field: %s}", m.Value)
  3. }

If the underlying type of myType is a number, string or other simple type, then convert to the underlying type when printing:

  1. func (m mType) String() string {
  2. return fmt.Sprint(int(m))
  3. }

答案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中所解释的,只需将其转换回表示的类型即可:

  1. type Foo int
  2. func (f Foo) String() string {
  3. if f == 0 {
  4. return "foo"
  5. }
  6. return fmt.Sprintf("%v", int(f)) // 注意
  7. }
  8. func main() {
  9. fmt.Println(Foo(0))
  10. fmt.Println(Foo(42))
  11. }

Playground

**编辑:**正如其他人在评论中指出的,如果你的类型是一个结构体,除了将其转换为具有相同字段的匿名结构体类型,使用%#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:

  1. type Foo int
  2. func (f Foo) String() string {
  3. if f == 0 {
  4. return "foo"
  5. }
  6. return fmt.Sprintf("%v", int(f)) // N.B.
  7. }
  8. func main() {
  9. fmt.Println(Foo(0))
  10. fmt.Println(Foo(42))
  11. }

Playground.

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.

huangapple
  • 本文由 发表于 2014年9月24日 22:29:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/26019503.html
匿名

发表评论

匿名网友

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

确定