打印Go类型忽略" String()字符串"方法

时间:2014-09-24 14:29:12

标签: interface go formatting printf

如果我有这样的类型:

type myType ...

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

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

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

3 个答案:

答案 0 :(得分: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))
}

答案 1 :(得分:3)

使用%#v代替%v

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

答案 2 :(得分:2)

如果您希望让基础类型%#v正常工作或您的类型是类型别名,则使用String格式不是正确的答案。

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

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