ホームページ > バックエンド開発 > Golang > 「fmt.Sprintf」の使用時にメソッド レシーバーをポインターから非ポインターに変更するとデッド ループが発生するのはなぜですか?

「fmt.Sprintf」の使用時にメソッド レシーバーをポインターから非ポインターに変更するとデッド ループが発生するのはなぜですか?

DDD
リリース: 2024-11-16 01:10:02
オリジナル
225 人が閲覧しました

Why Does Changing a Method Receiver from Pointer to Non-Pointer Lead to a Dead Loop When Using `fmt.Sprintf`?

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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート