This is how the fmt package is implemented, so you cannot change it.
But you can write a helper function that uses reflect package to iterate over the fields of the structure and can call the String() method in the fields if they have such a method.
Implementation Example:
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() }
Now that you want to print the struct , you can do:
fmt.Println(PrintStruct(a, true))
You can also add the String() method to your structure, which just needs to call our PrintStruct() function:
func (a A) String() string { return PrintStruct(a, true) }
Whenever you change the structure, you do not need to do anything with your String() method, since it uses reflection to dynamically jump across all fields.
Notes:
Since we use reflection, you need to export the t time.Time field in t time.Time for this to work (several additional fields are added for testing purposes):
type A struct { T time.Time I int unexported string }
Testing:
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))
Exit (try Go to the 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