Go 文字列フォーマットにおける "t" と "*t" の違いを理解する
Go プログラムでは、変数名にプレフィックスを付けることができますポインターの種類を示すアスタリスク (*) が付いています。この区別は、fmt パッケージを使用した文字列フォーマットのコンテキストにおいて重要です。
質問:
次のコードを考えてください:
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()) }
理由String にポインター レシーバー (func (t *TT) String() string) がある場合、コードは機能しますが、レシーバーが存在する場合、デッド ループが発生します。は非ポインタ型 (func (t TT) String() string) ですか?
答え:
fmt パッケージは String() の存在をチェックします。受け取るオペランドのメソッド。 String の受信側がポインター型の場合、基本型のメソッド セットには String() が含まれていないため、fmt パッケージはそれを呼び出しません。
一方、受信側が非ポインターの場合は、 type の String() は、基本型のメソッド セットに含まれます。これは、fmt パッケージが String() を呼び出すことを意味します。この場合、これは呼び出されるのと同じメソッドであり、無限ループにつながります。
予防:
回避するにはこの無限ループでは、type キーワードを使用して新しい型を作成し、書式設定されている値に型変換を適用することを検討してください。
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
Thisこのアプローチでは、type キーワードによって作成された新しい型内で String() メソッドを分離することで、間接的な再帰を防ぎます。
以上が`String()` メソッドにポインタ レシーバを使用すると、Go 文字列フォーマットでのデッド ループが防止されるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。