为了账号安全,请及时绑定邮箱和手机立即绑定

附加到作为空接口传递的 golang 切片

附加到作为空接口传递的 golang 切片

Go
ABOUTYOU 2022-10-10 19:23:51
如何附加到空接口(已验证为 *[] 结构)?func main() {  var mySlice []myStruct // myStruct can be any struct (dynamic)  decode(&mySlice, "...")}func decode(dest interface{}, src string) {  // assume dest has been verified to be *[]struct  var modelType reflect.Type = getStructType(dest)  rows, fields := getRows(src)  for _, row := range rows {    // create new struct of type modelType and assign all fields    model := reflect.New(modelType)    for field := fields {      fieldValue := getRowValue(row, field)      model.Elem().FieldByName(field).Set(fieldValue)    }    castedModelRow := model.Elem().Interface()          // append model to dest; how to do this?    // dest = append(dest, castedModelRow)  }}我尝试过的事情:这简直是恐慌:反射:在 ptr 值上调用 reflect.Append(因为我们通过 &mySlice 而不是 mySlice)dest = reflect.Append(reflect.ValueOf(dest), reflect.ValueOf(castedModelRow))这有效,但不会将值设置回 dest... 在 main func 中,调用 decode 函数后 len(mySlice) 保持为 0。func decode(dest interface{}, src string) {  ...  result := reflect.MakeSlice(reflect.SliceOf(modelType), rowCount, rowCount)  for _, row : range rows {    ...    result = reflect.Append(result, reflect.ValueOf(castedModelRow))  }  dest = reflect.ValueOf(result)}
查看完整描述

2 回答

?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

这是修复问题中decode显示的第二个功能的方法。该声明


dest = reflect.ValueOf(result)

修改局部变量dest,而不是调用者的值。使用以下语句修改调用者的切片:


reflect.ValueOf(dest).Elem().Set(result)

问题中的代码在 reflect.MakeSlice 中创建的元素之后附加了解码的元素。结果切片具有len(rows)零值,后跟len(rows)解码值。通过更改修复


result = reflect.Append(result, reflect.ValueOf(castedModelRow))

至:


result.Index(i).Set(model)

decode这是问题中第二个函数的更新版本:


func decode(dest interface{}, src string) {

    var modelType reflect.Type = getStructType(dest)

    rows, fields := getRows(src)

    result := reflect.MakeSlice(reflect.SliceOf(modelType), len(rows), len(rows))

    for i, row := range rows {

        model := reflect.New(modelType).Elem()

        for _, field := range fields {

            fieldValue := getRowValue(row, field)

            model.FieldByName(field).Set(fieldValue)

        }

        result.Index(i).Set(model)

    }

    reflect.ValueOf(dest).Elem().Set(result)

}



查看完整回答
反对 回复 2022-10-10
?
青春有我

TA贡献1784条经验 获得超8个赞

您与原始解决方案非常接近。在调用附加操作之前,您必须取消引用指针。如果您的 dest 已经有一些现有元素并且您不想通过创建newSlice.


tempDest := reflect.ValueOf(dest).Elem()

tempDest = reflect.Append(tempDest, reflect.ValueOf(model.Interface()))

与@I Love Reflection 指出的类似,您最终需要将新切片设置回指针。


reflect.ValueOf(dest).Elem().Set(tempDest)

整体解码:


var modelType reflect.Type = getStructType(dest)

rows, fields := getRows(src)

tempDest := reflect.ValueOf(dest).Elem()

for _, row := range rows {

    model := reflect.New(modelType).Elem()

    for _, field := range fields {

        fieldValue := getRowValue(row, field)

        model.FieldByName(field).Set(fieldValue)

    }

    tempDest = reflect.Append(tempDest, reflect.ValueOf(model.Interface()))

}

reflect.ValueOf(dest).Elem().Set(tempDest)


查看完整回答
反对 回复 2022-10-10
  • 2 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信