これは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()
メソッドで何もする必要はありません。
注:
type A struct {
T time.Time
I int
unexported string
}
テスト:私たちは、リフレクションを使用しているので、あなたはこれが機能するためにt time.Time
フィールドをエクスポートする必要があり
は(もテスト目的のためにいくつかの余分なフィールドを追加しました)それ:
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() 'を使いたいと思います。 –
@ LaiYu-Hsuanあなたはそうです。編集済みの回答を参照してください。 – icza