ホームページ > バックエンド開発 > Golang > ポインタ レシーバが使用されない限り、Golang 構造体メソッド内のスライスへの追加が機能しないのはなぜですか?

ポインタ レシーバが使用されない限り、Golang 構造体メソッド内のスライスへの追加が機能しないのはなぜですか?

Linda Hamilton
リリース: 2024-12-31 15:09:10
オリジナル
440 人が閲覧しました

Why doesn't appending to a slice within a Golang struct method work unless a pointer receiver is used?

Golang では構造体のプロパティであるスライスに追加できないのはなぜですか?

Golang ではすべてが値によって渡されますつまり、オブジェクトが関数に引数として渡されるたびに、オブジェクトのコピーが作成されます。これにより、構造体のプロパティであるスライスに追加しようとすると、予期しない動作が発生する可能性があります。

問題: Test3

次の例を考えてみましょう:

package main

import "fmt"

type Test3 struct {
    all []int
}

func (c Test3) run() []int {
    c.combo()
    return c.all
}

func (c Test3) combo() {
    for i := 0; i < 2; i++ {
        c.all = append(c.all, i)
        fmt.Println("Test3 step", i+1, c.all)
    }
}

func main() {
    test3 := &Test3{}
    fmt.Println("Test3 final:", test3.run())
}
ログイン後にコピー

test3.run() を呼び出すと、test3 のコピーが作成され、実行に渡されます。次に run メソッドは combo を呼び出し、2 つの値を c.all に追加します。ただし、run が戻ると、test3 のコピーが破棄されるため、c.all への変更は失われます。これにより、出力に見られるように、空のスライスが返されます。

Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: []
ログイン後にコピー

解決策: ポインター レシーバーの使用

この問題を解決するには、以下が必要です。コンボメソッドにポインタレシーバを使用します。これは、コピーの代わりに Test3 値へのポインターを渡すようにコンパイラーに指示します。

func (c *Test3) combo() {
    for i := 0; i < 2; i++ {
        c.all = append(c.all, i)
        fmt.Println("Test3 step", i+1, c.all)
    }
}
ログイン後にコピー

ポインター レシーバーを使用すると、コンボ内の c.all に加えられた変更は、元の Test3 値に直接適用されます。参照によって渡されます。これにより、正しい出力が得られます。

Test3 step 1 [0]
Test3 step 2 [0 1]
Test3 final: [0 1]
ログイン後にコピー

値渡しの概念を理解し、ポインター レシーバーを適切に使用することで、Golang 構造体でスライスを操作するときに予期しない動作を回避できます。

以上がポインタ レシーバが使用されない限り、Golang 構造体メソッド内のスライスへの追加が機能しないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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