Go – 通过反射向 []interface{} 追加元素

huangapple go评论75阅读模式
英文:

Go - Append to []interface{} via reflection

问题

没有反射的情况下,可以将多个类型添加到类型为 []interface{} 的列表中。像这样:

package main

import "fmt"

func main() {
    var foo []interface{}
    foo = append(foo, "Test")
    foo = append(foo, "Foo")
    foo = append(foo, 10)
    fmt.Printf("%v\n", foo)
}

使用反射是否可能实现这一点?我尝试了以下代码,但是出现了一个恐慌错误,提示:"panic: reflect.Set: value of type string is not assignable to type []interface {}"

package main

import (
    "fmt"
    "reflect"
)

func rf(inf interface{}) {
    val := reflect.Indirect(reflect.ValueOf(inf))
    field := val.FieldByName("Foo")
    rslice := reflect.MakeSlice(reflect.SliceOf(field.Type()), 0, 5)
    v := reflect.Indirect(reflect.ValueOf("Test"))
    rslice = reflect.Append(rslice, v)
}

func main() {
    var s struct {
        Foo []interface{}
    }
    rf(&s)
    fmt.Printf("%+v\n", s)
}
英文:

Without reflection it is possible to add multiple types to a list of type []interface{}. Like so:

package main

import "fmt"

func main() {
    var foo []interface{}
    foo = append(foo, "Test")
    foo = append(foo, "Foo")
    foo = append(foo, 10)
    fmt.Printf("%v\n", foo)
}

Is this possible with reflection? I try the following but I get a panic saying: "panic: reflect.Set: value of type string is not assignable to type []interface {}"

package main

import (
    "fmt"
    "reflect"
)

func rf(inf interface{}) {
    val := reflect.Indirect(reflect.ValueOf(inf))
    field := val.FieldByName("Foo")
    rslice := reflect.MakeSlice(reflect.SliceOf(field.Type()), 0, 5)
    v := reflect.Indirect(reflect.ValueOf("Test"))
    rslice = reflect.Append(rslice, v)
}

func main() {
    var s struct {
	    Foo []interface{}
    }
    rf(&s)
    fmt.Printf("%+v\n", s)
}

答案1

得分: 5

Foo字段已经是[]interface{}类型,所以SliceOf创建了一个[][]interface{}类型,这就是你看到的错误的原因。

移除SliceOf,然后使用field.Set(rslice)将新值设置回结构体字段。

func rf(inf interface{}) {
    val := reflect.Indirect(reflect.ValueOf(inf))
    field := val.FieldByName("Foo")
    rslice := reflect.MakeSlice(field.Type(), 0, 5)
    v := reflect.Indirect(reflect.ValueOf("Test"))
    rslice = reflect.Append(rslice, v)
    field.Set(rslice)
}

http://play.golang.org/p/gWK3-cP_MN

英文:

The Foo field is already of type []interface{}, so SliceOf is creating a [][]interface{}, which is what causes the error you see.

Remove the SliceOf, and then use field.Set(rslice) to set the new value back to the struct field.

func rf(inf interface{}) {
	val := reflect.Indirect(reflect.ValueOf(inf))
	field := val.FieldByName("Foo")
	rslice := reflect.MakeSlice(field.Type(), 0, 5)
	v := reflect.Indirect(reflect.ValueOf("Test"))
	rslice = reflect.Append(rslice, v)
	field.Set(rslice)
}

http://play.golang.org/p/gWK3-cP_MN

huangapple
  • 本文由 发表于 2016年4月14日 21:35:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/36624811.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定