ホームページ >バックエンド開発 >Golang >Go 範囲ループで構造体を変更しても元のスライスが更新されないのはなぜですか?

Go 範囲ループで構造体を変更しても元のスライスが更新されないのはなぜですか?

DDD
DDDオリジナル
2024-12-20 10:45:09436ブラウズ

Why doesn't modifying a struct in a Go range loop update the original slice?

Go での構造体のレンジング

Go では、構造体のスライスをレンジングする場合、範囲変数から取得した値がコピーされます。そのため、これらの値に加えられた変更は、元のスライスには影響しません。

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

package main

import (
    "fmt"
)

type myStruct struct {
    Name  string
    Count int
}

func main() {
    chartRecords := []myStruct{}

    for i := 0; i < 5; i++ {
        n := myStruct{Count: i, Name: fmt.Sprintf("Joe%2d", i)}
        chartRecords = append(chartRecords, n)
    }

    fmt.Printf("======ORIGINAL VALUES========\n")
    for _, elem := range chartRecords {
        fmt.Printf("No: %2d | Count: %2d | Name = %s\n", elem.Count, elem.Name)
    }

    fmt.Printf("======MODIFIED VALUES EXPECTED========\n")
    for _, elem := range chartRecords {
        elem.Count++
        fmt.Printf("No: %2d | Count: %2d | Name = %s\n", elem.Count, elem.Name)
    }

    fmt.Printf("======CHECK AGAIN AND VALUES ARE BACK TO ORIGINAL========\n")
    for _, elem := range chartRecords {
        fmt.Printf("No: %2d | Count: %2d | Name = %s\n", elem.Count, elem.Name)
    }
}

このコードを実行すると、次の出力が生成されます:

======ORIGINAL VALUES========
No:  0 | Count:  0 | Name = Joe 0
No:  1 | Count:  1 | Name = Joe 1
No:  2 | Count:  2 | Name = Joe 2
No:  3 | Count:  3 | Name = Joe 3
No:  4 | Count:  4 | Name = Joe 4
======MODIFIED VALUES EXPECTED========
No:  1 | Count:  1 | Name = Joe 0
No:  2 | Count:  2 | Name = Joe 1
No:  3 | Count:  3 | Name = Joe 2
No:  4 | Count:  4 | Name = Joe 3
No:  5 | Count:  5 | Name = Joe 4
======CHECK AGAIN AND VALUES ARE BACK TO ORIGINAL========
No:  0 | Count:  0 | Name = Joe 0
No:  1 | Count:  1 | Name = Joe 1
No:  2 | Count:  2 | Name = Joe 2
No:  3 | Count:  3 | Name = Joe 3
No:  4 | Count:  4 | Name = Joe 4

ご覧のとおり、範囲内の各要素の Count フィールドをインクリメントしたにもかかわらず、chartRecords スライスの値は変更されていません。これは、範囲変数 elem がスライス内の元の要素のコピーであるためです。

元のスライスを更新するには、更新された要素を対応するインデックスのスライスに割り当てる必要があります:

for i, elem := range chartRecords {
    elem.Count++
    chartRecords[i] = elem
}

この修正により、コードを再度実行すると、次の出力が生成されます。

======ORIGINAL VALUES========
No:  0 | Count:  0 | Name = Joe 0
No:  1 | Count:  1 | Name = Joe 1
No:  2 | Count:  2 | Name = Joe 2
No:  3 | Count:  3 | Name = Joe 3
No:  4 | Count:  4 | Name = Joe 4
======MODIFIED VALUES EXPECTED========
No:  1 | Count:  1 | Name = Joe 0
No:  2 | Count:  2 | Name = Joe 1
No:  3 | Count:  3 | Name = Joe 2
No:  4 | Count:  4 | Name = Joe 3
No:  5 | Count:  5 | Name = Joe 4
======CHECK AGAIN AND VALUES ARE STILL MODIFIED========
No:  1 | Count:  1 | Name = Joe 0
No:  2 | Count:  2 | Name = Joe 1
No:  3 | Count:  3 | Name = Joe 2
No:  4 | Count:  4 | Name = Joe 3
No:  5 | Count:  5 | Name = Joe 4

これで、chartRecords スライスの値が次のように更新されます。

以上がGo 範囲ループで構造体を変更しても元のスライスが更新されないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。