2

いいねして別のスライスに追加し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

ゴラン遊び場

4

3 に答える 3

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.Valuereflect.Value[]int

遊び場の例

于 2016-08-28T16:04:35.663 に答える
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{} に割り当てることができないのはなぜですか?」という質問があります。

なんで?

これには主に 2 つの理由があります。

1 つ目は、[]interface{} 型の変数はインターフェイスではないということです! これは、要素の型がたまたま interface{} であるスライスです。しかし、それを踏まえても、その意味は明らかであると言えます。

そうですね?[]interface{} 型の変数には、コンパイル時に認識される特定のメモリ レイアウトがあります。

各 interface{} は 2 つの単語を使用します (1 つの単語は含まれているものの型を表し、もう 1 つの単語は含まれているデータまたはデータへのポインターのいずれかを表します)。結果として、長さが N でタイプが []interface{} のスライスは、長さが N*2 ワードのデータのチャンクによってサポートされます。

これは、タイプが []MyType で同じ長さのスライスを裏付けるデータのチャンクとは異なります。そのデータのチャンクは、N*sizeof(MyType) ワードの長さになります。

その結果、[]MyType 型のものを []interface{} 型のものにすばやく割り当てることはできません。それらの背後にあるデータは異なって見えるだけです。

于 2016-08-28T18:07:26.617 に答える
0

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

于 2016-08-28T16:22:07.683 に答える