如何 reflect.New 切片并将其 reflect.AppendSlice 到源切片
How to reflect.New a slice and reflect.AppendSlice it to a source slice
我想 reflect.New
像 []int
一样的 []interface{}
并将其附加到另一个切片中。
我的代码一定有错误,但我不知道如何正确,也不知道如何深入理解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
恐慌在这一行:
value = reflect.AppendSlice(value, reflect.ValueOf(s.Elem()))
值 s.Elem()
是 reflect.Value
。在对 AppendSlice
:
的调用中直接使用此值
value = reflect.AppendSlice(value, s.Elem())
表达式reflect.ValueOf(s.Elem())
returnsreflect.Value
为reflect.Value
,不为底层[]int
。
第 21 行错误:
value = reflect.AppendSlice(value, reflect.ValueOf(s.Elem()))
参见文档:
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
试试这个工作示例(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 :
The question then, "Why can't I assign any slice to an []interface{},
when I can assign any type to an interface{}?"
Why?
There are two main reasons for this.
The first is that a variable with type []interface{} is not an
interface! It is a slice whose element type happens to be interface{}.
But even given this, one might say that the meaning is clear.
Well, is it? A variable with type []interface{} has a specific memory
layout, known at compile time.
Each interface{} takes up two words (one word for the type of what is
contained, the other word for either the contained data or a pointer
to it). As a consequence, a slice with length N and with type
[]interface{} is backed by a chunk of data that is N*2 words long.
This is different than the chunk of data backing a slice with type
[]MyType and the same length. Its chunk of data will be
N*sizeof(MyType) words long.
The result is that you cannot quickly assign something of type
[]MyType to something of type []interface{}; the data behind them just
look different.
我想 reflect.New
像 []int
一样的 []interface{}
并将其附加到另一个切片中。
我的代码一定有错误,但我不知道如何正确,也不知道如何深入理解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
恐慌在这一行:
value = reflect.AppendSlice(value, reflect.ValueOf(s.Elem()))
值 s.Elem()
是 reflect.Value
。在对 AppendSlice
:
value = reflect.AppendSlice(value, s.Elem())
表达式reflect.ValueOf(s.Elem())
returnsreflect.Value
为reflect.Value
,不为底层[]int
。
第 21 行错误:
value = reflect.AppendSlice(value, reflect.ValueOf(s.Elem()))
参见文档:
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
试试这个工作示例(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 :
The question then, "Why can't I assign any slice to an []interface{}, when I can assign any type to an interface{}?"
Why?
There are two main reasons for this.
The first is that a variable with type []interface{} is not an interface! It is a slice whose element type happens to be interface{}. But even given this, one might say that the meaning is clear.
Well, is it? A variable with type []interface{} has a specific memory layout, known at compile time.
Each interface{} takes up two words (one word for the type of what is contained, the other word for either the contained data or a pointer to it). As a consequence, a slice with length N and with type []interface{} is backed by a chunk of data that is N*2 words long.
This is different than the chunk of data backing a slice with type []MyType and the same length. Its chunk of data will be N*sizeof(MyType) words long.
The result is that you cannot quickly assign something of type []MyType to something of type []interface{}; the data behind them just look different.