String 如何使用字段的字符串()打印结构?

String 如何使用字段的字符串()打印结构?,string,go,struct,String,Go,Struct,此代码: type A struct { t time.Time } func main() { a := A{time.Now()} fmt.Println(a) fmt.Println(a.t) } 印刷品: {{63393490800 0 0x206da0}} 2009-11-10 23:00:00 +0000 UTC A未实现String(),因此它不是fmt.Stringer,并打印其本机表示形式。但是,为我要打印的每个结构实现String()非常

此代码:

type A struct {
    t time.Time
}

func main() {
    a := A{time.Now()}
    fmt.Println(a)
    fmt.Println(a.t)
}
印刷品:

{{63393490800 0 0x206da0}}
2009-11-10 23:00:00 +0000 UTC

A
未实现
String()
,因此它不是
fmt.Stringer
,并打印其本机表示形式。但是,为我要打印的每个结构实现
String()
非常繁琐。更糟糕的是,如果添加或删除某些字段,我必须更新
String()
s。是否有一种更简单的方法来打印结构,以及它的字段“
String()
s?”

这就是
fmt
包的实现方式,因此您不能更改它

但是您可以编写一个helper函数,该函数使用反射(包)在结构的字段上迭代,并且可以在字段上调用
String()
方法(如果字段有这样的方法)

实施示例:

func PrintStruct(s interface{}, names bool) string {
    v := reflect.ValueOf(s)
    t := v.Type()
    // To avoid panic if s is not a struct:
    if t.Kind() != reflect.Struct {
        return fmt.Sprint(s)
    }

    b := &bytes.Buffer{}
    b.WriteString("{")
    for i := 0; i < v.NumField(); i++ {
        if i > 0 {
            b.WriteString(" ")
        }
        v2 := v.Field(i)
        if names {
            b.WriteString(t.Field(i).Name)
            b.WriteString(":")
        }
        if v2.CanInterface() {
            if st, ok := v2.Interface().(fmt.Stringer); ok {
                b.WriteString(st.String())
                continue
            }
        }
        fmt.Fprint(b, v2)
    }
    b.WriteString("}")
    return b.String()
}
您还可以选择将
String()
方法添加到您的结构中,该方法只需调用我们的
PrintStruct()
函数:

func (a A) String() string {
    return PrintStruct(a, true)
}
无论何时更改结构,都不必使用
String()
方法,因为它使用反射动态遍历所有字段

注意事项:

由于我们使用的是反射,您必须导出
t time.time
字段才能使其工作(还添加了一些额外字段用于测试):

测试它:

a := A{time.Now(), 2, "hi!"}
fmt.Println(a)
fmt.Println(PrintStruct(a, true))
fmt.Println(PrintStruct(a, false))
fmt.Println(PrintStruct("I'm not a struct", true))
输出(在上尝试):


这正是我试图避免的。我想使用
time.time
String()
,而不是公开其内部实现。
type A struct {
    T          time.Time
    I          int
    unexported string
}
a := A{time.Now(), 2, "hi!"}
fmt.Println(a)
fmt.Println(PrintStruct(a, true))
fmt.Println(PrintStruct(a, false))
fmt.Println(PrintStruct("I'm not a struct", true))
{T:2009-11-10 23:00:00 +0000 UTC I:2 unexported:hi!}
{T:2009-11-10 23:00:00 +0000 UTC I:2 unexported:hi!}
{2009-11-10 23:00:00 +0000 UTC 2 hi!}
I'm not a struct