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

编程入门 行业动态 更新时间:2024-10-14 04:23:46
本文介绍了如何使用字段的 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?

A doesn't implement String(), so it's not a fmt.Stringer and prints its native representation. But is very tedious to implement String() for every single struct I want to print. Worse, I have to update the String()s if I add or remove some fields. Is there an easier way to print a struct, with its fields' String()s?

推荐答案

fmt 包就是这样实现的,所以你不能改变它.

This is how the fmt package is implemented, so you can't change that.

但是您可以编写一个使用反射的辅助函数(reflectpackage) 来遍历结构体的字段,并且可以在字段上调用 ​​String() 方法(如果它们有这样的方法).

But you can write a helper function which uses reflection (reflect package) to iterate over the fields of a struct, and can call the String() method on the fields if they have such a method.

示例实现:

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

现在当你想打印一个struct时,你可以这样做:

Now when you want to print a struct, you can do:

fmt.Println(PrintStruct(a, true))

您也可以选择将 String() 方法添加到您的结构中,该方法只需调用我们的 PrintStruct() 函数:

You may also choose to add a String() method to your struct which just has to call our PrintStruct() function:

func (a A) String() string { return PrintStruct(a, true) }

无论何时更改结构,您都不必对 String() 方法做任何事情,因为它使用反射动态遍历所有字段.

Whenever you change your struct, you don't have to do anything with your String() method as it uses reflection to dynamically walk over all the fields.

注意事项:

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

Since we're using reflection, you have to export the t time.Time field for this to work (also added a few extra fields for testing purposes):

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

输出(在 Go Playground 上试试):

Output (try it on the Go Playground):

{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() 打印结构?

本文发布于:2023-11-27 13:11:44,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1638215.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:字段   如何使用   结构   String

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!