Go sqlx中如何获取切片的切片(而非Map)存储查询全量结果?
如何用sqlx实现类似Python cursor.fetchall()的切片的切片结果
注意:此问题并非重复《Create a Map in Golang from database Rows》,后者是将数据库行读取为Map,而本文需要将行读取为切片(需保留顺序,Map无法满足)。需求是使用sqlx获取表示查询所有行和列的切片的切片,效果类似Python的
cursor.fetchall()返回结果。
当前已实现的逐行读取方式:
var results []interface{} for rows.Next() { cols, err := rows.SliceScan() checkErr(err) results = append(results, cols) }
在sqlx文档中看到如下返回单一字段切片的示例:
var names []string err = db.Select(&names, "SELECT name FROM place LIMIT 10")
尝试直接用Select实现切片的切片时触发报错:
results := make([][]interface{}, 0) err := db.Select(&results, "select * from foo") // panic: non-struct dest type slice with >1 columns (5)
解决方法
sqlx的Select方法设计上只支持映射到结构体切片或单一基础类型切片,无法直接处理[][]interface{}这种嵌套切片类型。要实现类似Python fetchall()的效果,最直接可靠的方式是基于Queryx获取行对象后,通过SliceScan逐行读取并收集结果,你最初的思路是对的,只需调整类型定义让语义更清晰:
// 明确定义结果为[][]interface{}类型 var results [][]interface{} rows, err := db.Queryx("select * from foo") if err != nil { // 这里添加你的错误处理逻辑,比如log.Fatal(err) } defer rows.Close() for rows.Next() { cols, err := rows.SliceScan() if err != nil { // 错误处理 } results = append(results, cols) } // 必须检查遍历结束后的行错误 if err := rows.Err(); err != nil { // 错误处理 }
如果需要频繁使用这个功能,可以封装成一个工具函数:
// FetchAll 模拟Python cursor.fetchall(),返回切片的切片结果 func FetchAll(db *sqlx.DB, query string, args ...interface{}) ([][]interface{}, error) { rows, err := db.Queryx(query, args...) if err != nil { return nil, err } defer rows.Close() var results [][]interface{} for rows.Next() { cols, err := rows.SliceScan() if err != nil { return nil, err } results = append(results, cols) } return results, rows.Err() } // 使用示例 results, err := FetchAll(db, "select * from foo where id > ?", 10) if err != nil { // 错误处理 }
内容的提问来源于stack exchange,提问作者Mark Harrison
相关产品推荐
相关产品推荐

