t と *t の違いを理解する
このコード スニペットには、fmt を実装する String メソッドを持つ TT 型があります。 .Stringer インターフェイス:
package main import "fmt" type TT struct { a int b float32 c string } func (t *TT) String() string { return fmt.Sprintf("%+v", *t) } func main() { tt := &TT{3, 4, "5"} fmt.Printf(tt.String()) }
このコードは、fmt パッケージがあるため機能します。 String メソッドを呼び出して、TT 値の文字列表現を取得します。
ただし、非ポインタ レシーバを受け取るように String メソッドが変更されると、
func (t *TT) String() string { return fmt.Sprintf("%+v", t) }
デッド ループが発生します。 。その理由を説明しましょう。
fmt.Sprintf("% v", t) を呼び出すと、*TT (TT へのポインター) 値が fmt パッケージに渡されます。 TT.String メソッドにはポインター レシーバーがあるため、fmt パッケージは *TT タイプのメソッド セット内でこのメソッドを見つけられません。
レシーバーを非ポインター タイプに変更すると、fmt パッケージはTT のメソッド セットで String メソッドを見つけます。ただし、呼び出されるメソッドが値のフォーマットに使用されるメソッドと同じであるため、これは無限再帰につながります。
この問題を回避するには、type キーワードを使用して新しい型を作成し、効果的にfmt パッケージに渡される値から受信者の型を取得します:
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
これは、type キーワードによって作成された新しい型にはメソッドがないため機能します。そのため、fmt パッケージには新しい型で String メソッドを呼び出そうとしません。
以上が「fmt.Sprintf」の使用時にメソッド レシーバーをポインターから非ポインターに変更するとデッド ループが発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。