使用反射将元素添加到Go语言切片

5

由于某些原因,使用反射向切片中添加新元素似乎不会更新切片本身。以下是演示代码:

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
}

实验室链接:https://play.golang.org/p/j3532H_mUL

这里有什么我忽略的东西吗?

2个回答

16

reflect.Append 的工作方式类似于 append,会返回一个新的切片值。

appendToSlice 函数中,您将该值赋给了 value 变量,这替换了之前的 reflect.Value,但并未更新原始参数。

为了更清楚地说明发生了什么,请看不使用反射的示例函数:

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

您需要使用Value.Set方法来更新原始值:

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


3
    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)
    }


请看:

https://play.golang.org/p/vXOqTVSEleO,此链接为it技术相关内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接