这是如何实现fmt
包,所以你不能改变它。
但是,您可以编写一个帮助函数,它使用反射(reflect
包)遍历结构的字段,并且可以在字段上调用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()
}
现在,当你想打印struct
,你可以这样做:
fmt.Println(PrintStruct(a, true))
您也可以选择一个String()
方法添加到您的结构刚刚有打电话给我们PrintStruct()
功能:
func (a A) String() string {
return PrintStruct(a, true)
}
无论何时您更改结构,您都不必使用String()
方法执行任何操作,因为它使用反射来动态遍历所有字段。
注:
由于我们使用反射,你要导出t time.Time
场这个工作(还增加了用于测试的一些额外的字段):
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):
{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
这正是我试图避免的。我想使用'time.Time'的'String()',而不是公开它的内部实现。 –
@赖玉轩你说得对。见编辑的答案。 – icza