Go 如何从嵌套接口获取值

Go 如何从嵌套接口获取值,go,reflection,odbc,Go,Reflection,Odbc,我在尝试使用和不使用ORM从数据库中动态读取字符串时遇到了一个小问题 也许值得一提的是,使用另一个SQL server驱动程序,我以字符串形式接收数据,而不是[]uint8,这解决了我的问题) 我使用以下代码将一行扫描到切片数组中: func createEmptyResultSet(numOfCols int) []interface{} { res := make([]interface{}, numOfCols) for col := 0; col < numOfCols; col+

我在尝试使用和不使用ORM从数据库中动态读取字符串时遇到了一个小问题

也许值得一提的是,使用另一个SQL server驱动程序,我以字符串形式接收数据,而不是[]uint8,这解决了我的问题)

我使用以下代码将一行扫描到切片数组中:

func createEmptyResultSet(numOfCols int) []interface{} {
res := make([]interface{}, numOfCols)
for col := 0; col < numOfCols; col++ {
    var i interface{}
    res[col] = &i
}
return res
我正在尝试访问以下切片:

使用以下代码的几个版本:

  for i := range values {
//also tried multiple get value
                t := reflect.TypeOf(values[i])
                if t.Kind() == reflect.Slice {
                    row[cols[i]] = interfaceSliceToString(values[i])
                } else {
                    row[cols[i]] = values[i]
                }
            }
但似乎什么都不管用。
有什么建议吗?

值中的值具有类型
*接口{}
。对切片的测试永远不会成功

使用下面的函数来简化事情。此函数返回一个值片和一个指向值的指针片。使用第一个切片 用于访问值和作为要扫描的可变参数的第二个切片

func createEmptyResultSet(numOfCols int) (values []interface{}, args []interface{}) {
    values = make([]interface{}, numOfCols)
    args = make([]interface{}, numOfCols)
    for col := 0; col < numOfCols; col++ {
        args[col] = &values[col]
    }
    return
}
现在,
values
包含实际值,而不是指向该值的指针

使用类型断言而不是反射来查找
[]字节值

for i, v := range values {
   switch v := v.(type) {
   case []byte:
      row[cols[i]] = string(v)
   default:
      row[cols[i]] = v
   }
}
以下是
rowsToStringInterfaceMapSlice
的完整代码:

func rowsToStringInterfaceMapSlice(rows *sql.Rows, cols []string) ([]map[string]interface{}, error) {
    var err error
    rowsRes := make([]map[string]interface{}, 0)
    numOfCols := len(cols)
    for rows.Next() {
        row := make(map[string]interface{}, numOfCols)
        values, args := createEmptyResultSet( numOfCols)
        if rows.Scan(args...); err != nil {
            return nil, err
        }
        for i, v := range values {
           switch v := v.(type) {
           case []byte:
              row[cols[i]] = string(v)
           default:
              row[cols[i]] = v
           }
        }
        rowsRes = append(rowsRes, row)
    }
    return rowsRes, nil
}
args
切片可以在行与行之间重复使用。 在循环外部分配
参数
,以降低内存压力

func rowsToStringInterfaceMapSlice(rows *sql.Rows, cols []string) ([]map[string]interface{}, error) {
    rowsRes := make([]map[string]interface{}, 0)
    values, args := createEmptyResultSet(len(cols))
    for rows.Next() {
        row := make(map[string]interface{}, len(cols))
        for i := range values {
            values[i] = nil
        }
        if err := rows.Scan(args...); err != nil {
            return nil, err
        }
        for i, v := range values {
            switch v := v.(type) {
            case []byte:
                row[cols[i]] = string(v)
            default:
                row[cols[i]] = v
            }
        }
        rowsRes = append(rowsRes, row)
    }
    return rowsRes, nil
}
func rowsToStringInterfaceMapSlice(rows *sql.Rows, cols []string) ([]map[string]interface{}, error) {
    var err error
    rowsRes := make([]map[string]interface{}, 0)
    numOfCols := len(cols)
    for rows.Next() {
        row := make(map[string]interface{}, numOfCols)
        values, args := createEmptyResultSet( numOfCols)
        if rows.Scan(args...); err != nil {
            return nil, err
        }
        for i, v := range values {
           switch v := v.(type) {
           case []byte:
              row[cols[i]] = string(v)
           default:
              row[cols[i]] = v
           }
        }
        rowsRes = append(rowsRes, row)
    }
    return rowsRes, nil
}
func rowsToStringInterfaceMapSlice(rows *sql.Rows, cols []string) ([]map[string]interface{}, error) {
    rowsRes := make([]map[string]interface{}, 0)
    values, args := createEmptyResultSet(len(cols))
    for rows.Next() {
        row := make(map[string]interface{}, len(cols))
        for i := range values {
            values[i] = nil
        }
        if err := rows.Scan(args...); err != nil {
            return nil, err
        }
        for i, v := range values {
            switch v := v.(type) {
            case []byte:
                row[cols[i]] = string(v)
            default:
                row[cols[i]] = v
            }
        }
        rowsRes = append(rowsRes, row)
    }
    return rowsRes, nil
}