Appending to go lang slice using reflection

最后都变了- 提交于 2020-12-30 10:45:08

问题


For some reason, it appears that adding new element to slice using reflection doesn't update slice itself. This is the code to demonstrate:

package main

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
}

Playground link : https://play.golang.org/p/j3532H_mUL

Is there something I'm missing here?


回答1:


reflect.Append works like append in that it returns a new slice value.

You are assigning this value to the value variable in the appendToSlice function, which replaces the previous reflect.Value, but does not update the original argument.

To make it more clear what's happening, take the equivalent function to your example without reflection:

func appendToSlice(arrPtr *[]int) {
    value := *arrPtr
    value = append(value, 55)
    fmt.Println(len(value))
}

What you need to use is the Value.Set method to update the original value:

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

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

    fmt.Println(value.Len())
}

https://play.golang.org/p/Nhabg31Sju




回答2:


    package main

    import "fmt"
    import "reflect"

    type Foo struct {
        Name string
    }

    func main() {
        _type := []Foo{}

        fmt.Printf("_type: v(%v) T(%T)\n", _type, _type)

        reflection := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(_type).Elem()), 0, 0)

        reflectionValue := reflect.New(reflection.Type())
        reflectionValue.Elem().Set(reflection)

        slicePtr := reflect.ValueOf(reflectionValue.Interface())

        sliceValuePtr := slicePtr.Elem()

        sliceValuePtr.Set(reflect.Append(sliceValuePtr, reflect.ValueOf(Foo{"a"})))
        sliceValuePtr.Set(reflect.Append(sliceValuePtr, reflect.ValueOf(Foo{"b"})))
        sliceValuePtr.Set(reflect.Append(sliceValuePtr, reflect.ValueOf(Foo{"c"})))

        values := []Foo{Foo{"d"}, Foo{"e"}}

        for _, val := range values {
            sliceValuePtr.Set(reflect.Append(sliceValuePtr, reflect.ValueOf(val)))
        }

        result := sliceValuePtr.Interface()

        fmt.Printf("result: %T = (%v)\n", result, result)
    }

take a look at: https://play.golang.org/p/vXOqTVSEleO



来源:https://stackoverflow.com/questions/42494333/appending-to-go-lang-slice-using-reflection

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!