Go 如何从嵌套接口获取值
我在尝试使用和不使用ORM从数据库中动态读取字符串时遇到了一个小问题 也许值得一提的是,使用另一个SQL server驱动程序,我以字符串形式接收数据,而不是[]uint8,这解决了我的问题) 我使用以下代码将一行扫描到切片数组中: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+
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
}