我希望reflect.New
和[]interface{}
一样[]int
并将其附加到另一个切片中。
我的代码必须有错误,但我不知道如何正确使用以及如何深入理解reflect.New
和reflect.AppendSlice
用法。
package main
import (
"fmt"
"reflect"
)
func main() {
var a []int
var value reflect.Value = reflect.ValueOf(&a)
if !value.CanSet() {
fmt.Println("go here", value.CanSet())
value = value.Elem()
fmt.Println("go here", value.CanSet())
}
fmt.Println("go here", value.Type())
s := reflect.New(value.Type())
fmt.Println("go here", s.Elem())
value = reflect.AppendSlice(value, reflect.ValueOf(s.Elem()))
value = reflect.AppendSlice(value, reflect.ValueOf([]int{1, 2}))
value = reflect.AppendSlice(value, reflect.ValueOf([]int{3, 4, 5, 6, 7, 8, 9}))
fmt.Println(value.Kind(), value.Slice(0, value.Len()).Interface())
//>>slice [1 2 3 4 5 6 7 8 9]
}
但是它给出了一个错误:
panic: reflect: call of reflect.AppendSlice on struct Value
goroutine 1 [running]:
panic(0x100a60, 0x1040e1a0)
/usr/local/go/src/runtime/panic.go:500 +0x720
reflect.flag.mustBe(0x99, 0x17)
/usr/local/go/src/reflect/value.go:201 +0xe0
reflect.AppendSlice(0xfa7e0, 0x1040e130, 0x197, 0x1116a0, 0x1040e190, 0x99, 0x0, 0x0, 0x0, 0x2)
/usr/local/go/src/reflect/value.go:1825 +0x60
main.main()
/tmp/sandbox476529744/main.go:21 +0x800
答案 0 :(得分:2)
恐慌就在这条线上:
value = reflect.AppendSlice(value, reflect.ValueOf(s.Elem()))
值s.Elem()
是reflect.Value
。在调用AppendSlice
:
value = reflect.AppendSlice(value, s.Elem())
表达式reflect.ValueOf(s.Elem())
会返回reflect.Value
的{{1}},而不会返回基础reflect.Value
。
答案 1 :(得分:1)
试试这个工作样本(The Go Playground):
package main
import (
"fmt"
"reflect"
)
func main() {
s := reflect.New(reflect.TypeOf([]interface{}{})).Elem()
s = reflect.Append(s, reflect.ValueOf(1))
s = reflect.AppendSlice(s, reflect.ValueOf([]interface{}{2, 3, 4, 5, 6, 7, 8, 9}))
fmt.Println(s)
}
输出:
[1 2 3 4 5 6 7 8 9]
请参阅:https://github.com/golang/go/wiki/InterfaceSlice:
接下来的问题是,“为什么我不能将任何切片分配给[]接口{}, 当我可以将任何类型分配给接口{}?“
为什么?
这有两个主要原因。
首先,类型为[] interface {}的变量不是 接口!它是一个切片,其元素类型恰好是接口{}。 但即使考虑到这一点,也许可以说意思很明确。
好吧,是吗?类型为[] interface {}的变量具有特定的内存 布局,在编译时已知。每个接口{}占用两个单词(一个单词表示什么是 包含,包含数据或指针的另一个词 它)。结果,一个长度为N且类型的切片 [] interface {}由一长N * 2个字的数据块支持。
这与支持切片类型的数据块不同 [] MyType和相同的长度。它的数据块将是 N * sizeof(MyType)字长。
结果是你不能快速分配某种类型的东西 [] MyType为[] interface {};他们背后的数据就是这样 看起来不一样。
答案 2 :(得分:0)
第21行出错:
value = reflect.AppendSlice(value, reflect.ValueOf(s.Elem()))
见doc:
func AppendSlice(s, t Value) Value
The slices s and t must have the same element type.
转储值时,您会看到:
Var dump s.Elem(): []int(nil)
Var dump reflect.ValueOf(s.Elem()): {typ:0xfa840 ptr:0x1040e160 flag:407}
Var dump value: []int(nil)
所以你只需要s.Elem()
请参阅:https://play.golang.org/p/KwXRxGyswg