Go 埋め込み型での String() メソッドの予期しない動作
Go で埋め込み型を使用する場合、埋め込み型のフィールドとメソッドは次のようになります。事実上、抱きしめるタイプに受け継がれています。これにより、特にカスタム String() メソッドを処理する場合に、予期しない動作が発生する可能性があります。
次の例を考えてみましょう:
type Engineer struct { Person TaxPayer Specialization string } type Person struct { Name string Age int } func (p Person) String() string { return fmt.Sprintf("name: %s, age: %d", p.Name, p.Age) } type TaxPayer struct { TaxBracket int } func (t TaxPayer) String() string { return fmt.Sprintf("%d", t.TaxBracket) }
このコードでは、Engineer タイプに Person タイプと TaxPayer タイプの両方が埋め込まれています。 、それぞれのデータをフォーマットするための独自の String() メソッドを定義します。ただし、Engineer オブジェクトをインスタンス化して fmt.Println(engineer) を呼び出した場合、出力は期待どおりではありません。
{name: John Doe, age: 35 3 Construction}
この出力は、Engineer.String() メソッドが呼び出されていることを示唆していますが、 TaxPayer.String() メソッドも結果に貢献しています。これは、String() メソッドが埋め込まれたときに Engineer タイプに昇格され、Person.String() メソッドと TaxPayer.String() メソッドの両方が呼び出しの対象となるためです。
これを明確にするために、次の点を考慮してください。シナリオ:
fmt.Println(engineer.String()) // Compile error: ambiguous selector engineer.String
この場合、エンジニアが複数のプロモートされた String() メソッドを持っているため、コンパイラーはエラーを発生させ、結果としてセレクターがあいまいになります。ただし、コンパイラがそのフィールドに基づいて Engineer のデフォルトの書式設定を自動的に選択するため、fmt.Println(engineer) は成功します。
この明らかな矛盾の理由は、fmt.Println() 関数が基本的に文字列変換を委任しているためです。 fmt パッケージに追加します。 fmt.Stringer インターフェイス (String() メソッドを定義する) を実装する値を見つけると、そのメソッドを呼び出して文字列表現を取得します。
この例では、 Person.String() とTaxPayer.String() は存在しますが、どちらも Engineer に昇格せず、デフォルトの書式設定が使用されます。ただし、fmt.Println(engineer.String()) の場合、コンパイラはあいまいなセレクターに遭遇し、エラーを発生させます。
結論として、埋め込み型は複数の場合に予期しない String() メソッドの動作を引き起こす可能性があります。埋め込み型はそのようなメソッドを定義します。潜在的な混乱を避け、望ましい出力を確保するには、埋め込みとメソッドのプロモーションの仕組みを理解することが重要です。
以上がGo の `fmt.Println` が埋め込み型と複数の `String()` メソッドを使用して予期しない出力を生成するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。