Mencetak Medan Struktur dengan String()
Kod ini:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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:
|
Salin selepas log masuk
{{63393490800 0 0x206da0}
10-11-2009 23:00:00 0000 UTC
1 2 3 4 5 | `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:
|
Salin selepas log masuk
func PrintStruct(santara muka{}, names bool) rentetan {
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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()
|
Salin selepas log masuk
}
1 2 3 4 5 6 | **Integrating the Helper Function**
With the custom function in place, structs can be printed by:
```go
fmt.Println(PrintStruct(a, true))
|
Salin selepas log masuk
Jika mahu , kaedah String() boleh ditambah pada struct, menggunakan PrintStruct() fungsi:
1 2 3 | func (a A) String() string {
return PrintStruct(a, true)
}
|
Salin selepas log masuk
Memandangkan kami menggunakan refleksi, adalah penting untuk mengeksport medan struct untuk kebolehcapaian oleh fungsi tersuai (menambah medan tambahan untuk tujuan ujian):
1 2 3 4 5 | type A struct {
T time.Time
I int
unexported string
}
|
Salin selepas log masuk
Praktikal Contoh
Kod lengkap:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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))
}
|
Salin selepas log masuk
Menguji ini kod menghasilkan:
1 2 3 4 5 6 | {{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
|
Salin selepas log masuk
Atas ialah kandungan terperinci Bagaimanakah saya boleh mencetak struct Go dengan mudah menggunakan kaedah String() medan mereka tanpa melaksanakan String() untuk setiap struct?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!