dtlrp119999 2015-01-16 18:33
浏览 34
已采纳

如何从interface {}值(反射)为显式类型的结构成员设置新值? Golang

I want to understand some subtle moments of using reflect package. Please, see example below, it describes better what I want to know:

type Robot struct {
    id    int
    model string
}

func change(i interface{}, fields ...string) {
        v := reflect.ValueOf(i).Elem()
        // here I emulate function by slice that could return any value,
        // so here I need to check if I can store incoming values to existing struct
        returns := []interface{}{100, "Something"}
        for i, name := range fields {
            x := reflect.ValueOf(&returns[i]).Elem()
            //check if value representing x is the same of struct member
            v.FieldByName(name).Set(x)
            // ^ here I want to store 100 to Robot.id when i = 0,
            // and "Something" to Robot.model when i = 1
        }


}

func main() {
    robot := &Robot{id: 1, model: "T310"}
    change(robot, "model", "id")
    // now robot become as follows: &Robot{100, "Something"}
}

Why does it need for?

    // It is need for retrieving values from sql DB into struct members 
    // (only for training purposes :))
    // Example:
    f := func(q string, structs interface{}, fields ...string) {
        rows, _ := db.Query(q)
        for i := 0; rows.Next(); i++ {
            rows.Scan(&structs[i])
            // very dirty here! it's hard to understand how to implement it
        }
    }
    var robots = []*Robot
    f("select id, model from robots", robots, "id", "model")
    // now each member of robots var should contain values from DB

I tried to be descriptive and explain as short as possible. I hope you understand me..

  • 写回答

1条回答 默认 最新

  • doufu8887 2015-01-16 19:36
    关注

    You can only set exported fields via reflection, so capitalize those first. Otherwise, if you're counting on positional values, make sure they are properly aligned.

    Something like this for example: http://play.golang.org/p/ItnjwwJnxe

    type Robot struct {
        ID    int
        Model string
    }
    
    func change(i interface{}, fields ...string) {
        returns := []interface{}{100, "Something"}
    
        v := reflect.ValueOf(i).Elem()
        for i, name := range fields {
            val := reflect.ValueOf(returns[i])
            v.FieldByName(name).Set(val)
        }
    }
    
    func main() {
        robot := &Robot{ID: 1, Model: "T310"}
        fmt.Println(robot)
        change(robot, "ID", "Model")
        fmt.Println(robot)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值