ホームページ >バックエンド開発 >Golang >元の Go スライスを Reflect.Append で変更できないのはなぜですか?それを修正するにはどうすればよいですか?

元の Go スライスを Reflect.Append で変更できないのはなぜですか?それを修正するにはどうすればよいですか?

DDD
DDDオリジナル
2024-12-04 10:51:101011ブラウズ

Why Doesn't Reflect.Append Modify the Original Go Slice, and How Can I Fix It?

リフレクションを使用した Go Lang スライスへの追加: メカニズムの理解

リフレクションを使用してスライスに新しい要素を追加しようとすると、次のようになります。それに応じて元のスライスが更新されることが期待されます。ただし、次のコードに示すように、これが発生しないことが観察される場合があります。

import (
    "fmt"
    "reflect"
)

func appendToSlice(arrPtr interface{}) {
    valuePtr := reflect.ValueOf(arrPtr)
    value := valuePtr.Elem()
    value = reflect.Append(value, reflect.ValueOf(55))

    fmt.Println(value.Len()) // prints 1
}

func main() {
    arr := []int{}
    appendToSlice(&arr)
    fmt.Println(len(arr)) // prints 0
}

理由を理解する

この動作を理解する鍵は次のとおりです。 Reflect.Append がどのように動作するかを認識する際に。標準ライブラリの append 関数と同様に、reflect.Append は、元のスライス値を変更する代わりに、新しいスライス値を作成します。上記のコード スニペットでは、値には新しく作成されたスライスが割り当てられます。これにより、関数内の元の値が置き換えられますが、関数外の元の引数には影響しません。

アプローチの修正

リフレクションを使用して元のスライスを変更するには、Value.Set メソッドを使用する必要があります。このメソッドを使用すると、元の値を更新できます。 appendToSlice 関数の修正バージョンは次のようになります。

func appendToSlice(arrPtr interface{}) {
    valuePtr := reflect.ValueOf(arrPtr)
    value := valuePtr.Elem()

    value.Set(reflect.Append(value, reflect.ValueOf(55)))

    fmt.Println(value.Len())
}

これにより、元のスライスが期待どおりに変更され、次の出力が得られます。

1
1

結論

リフレクションを使用してスライスを変更する場合は、reflect.Append によって新しいスライスが作成されることを考慮することが重要です。オリジナルを修正するよりも。 Value.Set メソッドを利用すると、リフレクションを使用して元のスライスを効果的に変更し、期待される結果が確実に達成されるようにすることができます。

以上が元の Go スライスを Reflect.Append で変更できないのはなぜですか?それを修正するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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