ホームページ > バックエンド開発 > Golang > Go Struct Setter 関数が元の構造体を変更しないのはなぜですか?

Go Struct Setter 関数が元の構造体を変更しないのはなぜですか?

Mary-Kate Olsen
リリース: 2024-12-21 10:00:17
オリジナル
699 人が閲覧しました

Why Doesn't My Go Struct Setter Function Modify the Original Struct?

構造体型のセッターについて

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

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