構造体型のセッターについて
Go では、構造体はセッター関数を通じて変更できます。ただし、構造体型のセッターを使用すると、特定の動作が予期しない可能性があります。次の例を考えてみましょう:
package main import "fmt" type T struct { Val string } // this setter seems not to work func (t T) SetVal(s string) { t.Val = s } // this setter, using ptr to T, seems to work ok func (t *T) SetVal2(s string) { (*t).Val = s } func main() { v := T{"abc"} fmt.Println(v) // prints {abc} v.SetVal("pdq") fmt.Println(v) // prints {abc}, was expecting {pdq}! v.SetVal2("xyz") fmt.Println(v) // prints {xyz}! }
なぜ SetVal 関数は元の構造体を期待どおりに変更しないのですか?
値のセマンティクスを理解する
主な違いは、構造体が関数に渡される方法にあります。 (SetVal のように) 構造体を値で渡す場合、関数内で構造体のコピーが作成されます。関数内で行われた変更は、この一時コピーにのみ影響し、元の構造体は変更されません。
ただし、構造体をポインターで渡す場合 (SetVal2 のように)、関数はメモリ内の元の構造体にアクセスできるようになります。関数内で行われた変更はすべて、元の構造体に直接反映されます。
Proof of Value Semantics
これは、関係する構造体のメモリ アドレスを出力することで説明できます。 :
package main import "fmt" type T struct { Val string } func (t T) SetVal(s string) { fmt.Printf("Address of copy is %p\n", &t) } func (t *T) SetVal2(s string) { fmt.Printf("Pointer argument is %p\n", t) } func main() { v := T{"abc"} fmt.Printf("Address of v is %p\n", &v) v.SetVal("pdq") v.SetVal2("xyz") }
このコードは出力を生成します次のようなもの:
Address of v is 0xf840001290 Address of copy is 0xf8400013e0 Pointer argument is 0xf840001290
出力される最初と 3 番目のアドレスは同じであり、同じ構造体を参照していることを示しています。ただし、2 番目のアドレスは異なり、SetVal 内で作成された一時コピーを表します。
以上がGo Struct Setter 関数が元の構造体を変更しないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。