使用 String() 打印结构体字段
此代码:
package main import ( "fmt" "time" ) type A struct { t time.Time } func main() { a := A{time.Now()} fmt.Println(a) fmt.Println(a.t) } ```` generates this output:
{{63393490800 0 0x206da0}}
2009-11-10 23:00:00 0000 UTC
`A` doesn't implement `String()`, so it doesn't conform to the `fmt.Stringer` interface and presents its internal representation. Implementing `String()` for every struct can be tedious, especially upon modifications to those structs. Is there a simpler method to print structs using their fields' `String()` methods? **The Custom Print Function** The fmt package's behavior in this case is intrinsic and cannot be changed. However, a helper function can be crafted using reflection (provided by the `reflect` package). The function iterates through a struct's fields and invokes their `String()` methods if they exist:
func PrintStruct(s 接口{}, 名称 bool) string {
v := reflect.ValueOf(s) t := v.Type() if t.Kind() != reflect.Struct { return fmt.Sprint(s) } var 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()
}
**Integrating the Helper Function** With the custom function in place, structs can be printed by: ```go fmt.Println(PrintStruct(a, true))
如果需要,可以将 String() 方法添加到结构体中,调用 PrintStruct() 函数:
func (a A) String() string { return PrintStruct(a, true) }
由于我们使用反射,导出结构体字段以便自定义函数可访问至关重要(为自定义函数添加了附加字段)测试目的):
type A struct { T time.Time I int unexported string }
实用示例
完整代码:
package main import ( "fmt" "reflect" "strings" "time" ) type A struct { T time.Time I int unexported string } func PrintStruct(s interface{}, names bool) string { v := reflect.ValueOf(s) t := v.Type() if t.Kind() != reflect.Struct { return fmt.Sprint(s) } var 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() } func (a A) String() string { return PrintStruct(a, true) } func main() { 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)) }
测试此代码会产生:
{{63393490800 0 0x206da0}} 2009-11-10 23:00:00 +0000 UTC {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
以上是如何使用字段的 String() 方法轻松打印 Go 结构,而不需要为每个结构实现 String() ?的详细内容。更多信息请关注PHP中文网其他相关文章!