虽然 fmt.Println 可以方便地显示内置类型,但其结构的行为可能很冗长且缺乏信息。考虑一个表示带有附加字段的时间值的结构:
type A struct { t time.Time }
使用 fmt.Println 打印此结构会导致:
{{63393490800 0 0x206da0}}
这不容易解释。具体来说,该结构体缺少 String() 方法,这会导致其字段无法根据需要进行格式化。
问题:
我们如何使用自定义字符串打印结构体其字段的表示形式,无需为每个字段显式定义 String() 方法struct?
解决方案:
反射可用于迭代结构体的字段并动态调用其 String() 方法。这是完成此操作的辅助函数:
func PrintStruct(s interface{}, names bool) string { v := reflect.ValueOf(s) t := v.Type() // Handle non-struct input if t.Kind() != reflect.Struct { return fmt.Sprint(s) } // Initialize buffer 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(":") } // Handle Stringer fields if v2.CanInterface() { if st, ok := v2.Interface().(fmt.Stringer); ok { b.WriteString(st.String()) continue } } // Print non-Stringer fields fmt.Fprint(b, v2) } b.WriteString("}") // Return formatted string return b.String() }
用法:
此函数可用于打印具有自定义字段的结构体格式:
a := A{time.Now()} fmt.Println(PrintStruct(a, true)) // Display field names fmt.Println(PrintStruct(a, false)) // Omit field names
注释:
为了更加方便,您可以为您的结构定义一个 String() 方法,该方法只需调用打印结构:
func (a A) String() string { return PrintStruct(a, true) }
以上是如何在不为每个结构显式定义 String() 方法的情况下自定义 Go 结构的打印?的详细内容。更多信息请关注PHP中文网其他相关文章!