dongshan7708 2016-06-21 08:36
浏览 120
已采纳

如何为切片反射添加元素?

Hi i am learning Go and i was doing some reflection. I got stuck in a case like this:

  1. I want to create a slice of struct passed to function as interface{}
  2. Then I want to append new elements to this slice

Here is a playground with the code example.

package main

import (
    "fmt"
    "reflect"
)

type A struct{ Name string }

func main() {
    bbb(A{})
}

func aaa(v interface{}) {
    sl := reflect.ValueOf(v).Elem()
    typeOfT := sl.Type()

    ptr := reflect.New(typeOfT).Interface()
    s := reflect.ValueOf(ptr).Elem()
    sl.Set(reflect.Append(sl, s))

    ptr = reflect.New(typeOfT).Interface()
    s = reflect.ValueOf(ptr).Elem()
    sl.Set(reflect.Append(sl, s))
}

func bbb(v interface{}) {
    myType := reflect.TypeOf(v)
    models := reflect.Zero(reflect.SliceOf(myType)).Interface()
    aaa(&models)

    fmt.Println(models)
}

Error: panic: reflect: call of reflect.Append on interface Value

Is there a way to make it work ? Note: that i want to work on a reference.

Solution:

Here is what i manage to do: playground.

  • 写回答

2条回答 默认 最新

  • douzhi1813 2016-06-22 11:50
    关注

    The problem was with reflect.Zero when i created slie with reflect.New it worked. Here you have full working example.

    https://play.golang.org/p/3mIEFqMxk-

    package main
    
    import (
        "encoding/json"
        "fmt"
        "reflect"
    )
    
    type A struct {
        Name string `column:"email"`
    }
    
    func main() {
        bbb(&A{})
    }
    
    func aaa(v interface{}) {
        t := reflect.TypeOf(v)
        if t.Kind() == reflect.Ptr {
            t = t.Elem()
        }
    
        if t.Kind() == reflect.Slice {
            t = t.Elem()
        } else {
            panic("Input param is not a slice")
        }
    
        sl := reflect.ValueOf(v)
    
        if t.Kind() == reflect.Ptr {
            sl = sl.Elem()
        }
    
        st := sl.Type()
        fmt.Printf("Slice Type %s:
    ", st)
    
        sliceType := st.Elem()
        if sliceType.Kind() == reflect.Ptr {
            sliceType = sliceType.Elem()
        }
        fmt.Printf("Slice Elem Type %v:
    ", sliceType)
    
        for i := 0; i < 5; i++ {
            newitem := reflect.New(sliceType)
            newitem.Elem().FieldByName("Name").SetString(fmt.Sprintf("Grzes %d", i))
    
            s := newitem.Elem()
            for i := 0; i < s.NumField(); i++ {
                col := s.Type().Field(i).Tag.Get("column")
                fmt.Println(col, s.Field(i).Addr().Interface())
            }
    
            sl.Set(reflect.Append(sl, newitem))
        }
    }
    
    func bbb(v interface{}) {
        t := reflect.TypeOf(v)
        if t.Kind() == reflect.Ptr {
            t = t.Elem()
        }
        if t.Kind() != reflect.Struct {
            panic("Input param is not a struct")
        }
    
        models := reflect.New(reflect.SliceOf(reflect.TypeOf(v))).Interface()
    
        aaa(models)
    
        fmt.Println(models)
    
        b, err := json.Marshal(models)
        if err != nil {
            panic(err)
        }
        fmt.Println(string(b))
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 易盾点选的cb参数怎么解啊
  • ¥15 MATLAB运行显示错误,如何解决?
  • ¥15 c++头文件不能识别CDialog
  • ¥15 Excel发现不可读取的内容
  • ¥15 UE5#if WITH_EDITOR导致打包的功能不可用
  • ¥15 关于#stm32#的问题:CANOpen的PDO同步传输问题
  • ¥20 yolov5自定义Prune报错,如何解决?
  • ¥15 电磁场的matlab仿真
  • ¥15 mars2d在vue3中的引入问题
  • ¥50 h5唤醒支付宝并跳转至向小荷包转账界面