使用反射附加到lang切片

问题描述 投票:1回答:2

出于某种原因,似乎使用反射向切片添加新元素不会更新切片本身。这是演示的代码:

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

这里有什么我想念的吗?

go reflection
2个回答
10
投票

reflect.Append就像append一样,它返回一个新的切片值。

您将此值分配给value函数中的appendToSlice变量,该变量替换先前的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


0
投票
    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

© www.soinside.com 2019 - 2024. All rights reserved.