2015-10-15 3 views
8

このコード:フィールドのString()でstructを印刷するには?

type A struct { 
    t time.Time 
} 

func main() { 
    a := A{time.Now()} 
    fmt.Println(a) 
    fmt.Println(a.t) 
} 

プリント:それはfmt.Stringerではありませんし、そのネイティブ表現を出力しますので、

{{63393490800 0 0x206da0}} 
2009-11-10 23:00:00 +0000 UTC 

Aは、String()を実装していません。しかし、私が印刷したいすべての構造体に対してString()を実装するのは非常に面倒です。さらに、フィールドを追加または削除すると、String()を更新する必要があります。フィールド 'String()'を使用して、構造体を印刷する簡単な方法はありますか?

答えて

4

これは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 
+0

これはまさに私が避けようとしていることです。私は内部実装を公開するのではなく、 'time.Time'の' String() 'を使いたいと思います。 –

+0

@ LaiYu-Hsuanあなたはそうです。編集済みの回答を参照してください。 – icza

関連する問題