使用反射附加到切片

时间:2017-10-25 10:20:41

标签: go reflection slice

我想仅使用反射附加到切片。但我无法弄清楚如何替换" a与新切片的值。

func main() {
    fmt.Println("Hello, playground")

    a := []string {"a","b","c"}

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

    v := reflect.ValueOf(a)

    fmt.Printf("%t\n\n", v.Type())
    fmt.Printf("%t\n\n", v.Type().Elem().Kind())

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

    fmt.Printf("%t - %v", a, a)
}

此代码可用于摆弄https://play.golang.org/p/cDlyH3jBDS

1 个答案:

答案 0 :(得分:1)

如果它来自非指针,则无法修改reflect.Value中包含的值。如果允许,您只能修改副本并导致更多混淆。切片值是包含指向后备阵列的指针,长度和容量的标头。当您将a传递给reflect.ValueOf()时,会生成并传递此标头的副本,您可以对其执行的任何修改都只能修改此标头副本。原始切片头不会观察到添加元素(从而改变其长度以及潜在的指针和容量),原始切片头仍将指向相同的数组,并且仍将包含相同的长度和容量值。有关详细信息,请参阅Are Golang function parameter passed as copy-on-write?;和Golang passing arrays to the function and modifying it

您必须从指针开始,并且可以使用Value.Elem()来获取指向的,解除引用的值的reflect.Value描述符。但你必须从指针开始。

在代码中更改此单行可使其正常工作:

v := reflect.ValueOf(&a).Elem()

并且要打印值的类型,请使用%T动词(%t用于bool值):

fmt.Printf("%T\n\n", v.Type())
fmt.Printf("%T\n\n", v.Type().Elem().Kind())

// ...

fmt.Printf("%T - %v", a, a)

输出(在Go Playground上尝试):

Hello, playground
*reflect.rtype

reflect.Kind

[]string - [a b c d e]

要更深入地了解Go的反思,请阅读博文:The Laws of Reflection

阅读相关问题+答案:

Assigning a value to struct member through reflection in Go

Changing pointer type and value under interface with reflection

Using reflection SetString