Как распечатать struct со строкой () полей?
этот код:
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?
1 ответов
это как fmt
пакет реализован, поэтому вы не можете изменить это.
но вы можете написать вспомогательную функцию, которая использует отражение (reflect
package) для итерации по полям структуры и может вызывать 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()
метод для вашей структуры, которая просто должна вызвать наш :
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