【问题标题】:Printing a Go type ignoring "String() string" method打印忽略“String() string”方法的 Go 类型
【发布时间】:2014-11-19 02:24:33
【问题描述】:

如果我有这样的输入:

type myType ...

func (m myType) String() string { ... }

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

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)
    }
}

【问题讨论】:

    标签: interface go formatting printf


    【解决方案1】:

    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))
    }
    

    【讨论】:

      【解决方案2】:

      使用%#v 而不是%v

      这不会调用 String()。 - 但如果你实现它,它将调用GoString()。

      【讨论】:

      • 这在 Effective Go 中有介绍。 OP 应该将该值转换为基础类型,然后使用%v 格式。看我的回答。
      • @Ainar-G 您的回答对于类型别名来说是微不足道的,但对于例如type myType struct { a myOtherType}。 Effective Go 中似乎也没有任何内容表明 %#v 不是 OP 想要的。
      【解决方案3】:

      如果你想让你的底层类型的String 工作或者你的类型是一个类型别名,那么使用%#v 格式不是正确的答案。

      正如Effective Go 中解释的那样,只需将其转换回它所代表的类型即可:

      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))
      }
      

      Playground.

      编辑:正如其他人在 cmets 中指出的那样,如果您的类型是结构,则使用 %#v 格式似乎是除了将其转换为具有相同字段的匿名结构类型之外的唯一方法。

      【讨论】:

      • 这只有在 myType 是一个类型别名时才真正有用。更常见的是它本身就是一个结构体。
      • 有什么不涉及显式转换的方法吗?我的用例是我有一个结构,创建它的匿名版本只是为了打印然后在两者之间进行转换会很痛苦。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-18
      • 2011-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-29
      • 1970-01-01
      相关资源
      最近更新 更多