英文:
How could I create a new struct from an unpredictable db.Query()?
问题
我正在使用db.query()
中的SELECT *
来返回表中的列。通常情况下,我会使用fmt.Scan()
将行扫描到预先声明的struct{}
中以进行进一步操作,但在这种情况下,表的列经常变化,所以我不能在Scan()
中使用已声明的struct{}
。
我一直在努力弄清楚如何根据db.query()
的列结果动态构建一个struct{}
,然后可以在Scan()
中使用它。我已经阅读了一些关于reflect
的内容,但我很难确定这是否适合我的用例,或者我是否需要考虑其他方法。
非常感谢任何指导。
英文:
I'm using SELECT *
in a db.query()
to return columns from a table. Typically, I would fmt.Scan()
the rows into a pre-declared struct{}
for further manipulation, but in this case, the table columns change frequently so I'm not able to use a declared struct{}
as part of my Scan()
.
I've been struggling to figure out how I might dynamically build a struct{}
based on the column results of the db.query()
which I could subsequently call on the use of for Scan()
. I've read a little about reflect
but I'm struggling to determine if this is right for my use-case or if I might have to think about something else.
Any pointers would be greatly appreciated.
答案1
得分: 1
你可以从结果行集中获取列名,并为扫描准备一个切片。
示例(https://go.dev/play/p/ilYmEIWBG5S):
package main
import (
"database/sql"
"fmt"
"log"
"github.com/DATA-DOG/go-sqlmock"
)
func main() {
// 模拟数据库
db, mock, err := sqlmock.New()
if err != nil {
log.Fatal(err)
}
columns := []string{"id", "status"}
mock.ExpectQuery("SELECT \\* FROM table").
WillReturnRows(sqlmock.NewRows(columns).AddRow(1, "ok"))
// 实际代码
rows, err := db.Query("SELECT * FROM table")
if err != nil {
log.Fatal(err)
}
cols, err := rows.Columns()
if err != nil {
log.Fatal(err)
}
data := make([]interface{}, len(cols))
strs := make([]sql.NullString, len(cols))
for i := range data {
data[i] = &strs[i]
}
for rows.Next() {
if err := rows.Scan(data...); err != nil {
log.Fatal(err)
}
for i, d := range data {
fmt.Printf("%s = %+v\n", cols[i], d)
}
}
}
此示例将所有列读入字符串。要检测列类型,可以使用rows.ColumnTypes
方法。
英文:
you can get column names from resulting rowset and prepare a slice for the scan.
Example (https://go.dev/play/p/ilYmEIWBG5S) :
package main
import (
"database/sql"
"fmt"
"log"
"github.com/DATA-DOG/go-sqlmock"
)
func main() {
// mock db
db, mock, err := sqlmock.New()
if err != nil {
log.Fatal(err)
}
columns := []string{"id", "status"}
mock.ExpectQuery("SELECT \\* FROM table").
WillReturnRows(sqlmock.NewRows(columns).AddRow(1, "ok"))
// actual code
rows, err := db.Query("SELECT * FROM table")
if err != nil {
log.Fatal(err)
}
cols, err := rows.Columns()
if err != nil {
log.Fatal(err)
}
data := make([]interface{}, len(cols))
strs := make([]sql.NullString, len(cols))
for i := range data {
data[i] = &strs[i]
}
for rows.Next() {
if err := rows.Scan(data...); err != nil {
log.Fatal(err)
}
for i, d := range data {
fmt.Printf("%s = %+v\n", cols[i], d)
}
}
}
This example reads all columns into strings. To detect column type one can use rows.ColumnTypes
method.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论