出于某种原因,似乎使用反射向切片添加新元素不会更新切片本身。这是演示的代码:
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
这里有什么我想念的吗?
答案 0 :(得分:9)
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())
}
答案 1 :(得分: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)
}