标签导航:

go语言数据库操作中db.queryrow(sql).scan函数能否将结果集扫描到map中?

在go语言中使用数据库时,经常会遇到需要将查询结果映射到结构体或map的情况。本文将探讨db.queryrow(sql).scan函数能否直接将查询结果扫描到一个map中,并分析代码示例中出现的问题及解决方法。

问题代码尝试将db.queryrow的结果扫描到一个map[string]*interface{}类型的变量res中。代码片段如下:

func selectone(id int) {
    res := map[string]*interface{}{"id": nil, "name": nil, "password": nil, "add_time": nil}
    fmt.println(res)

    sql := "select * from test where id = ?"
    err := db.queryrow(sql, id).scan(res["id"], res["name"], res["password"], res["add_time"])

    if err != nil {
        fmt.println("获取数据失败:", err.error())
    } else {
        fmt.println(res)
    }
}

这段代码的核心问题在于res的初始化。虽然声明了map[string]*interface{}类型,但是res["id"], res["name"]等元素的值都是nil。scan函数需要的是指向可修改变量的指针,而nil并不指向任何可用的内存地址。因此,scan函数会报错提示“不是一个指针”。

为了解决这个问题,需要在初始化res时为每个键值赋予一个有效的指针,例如:

res := map[string]*interface{}{"id": new(int), "name": new(string), "password": new(string), "add_time": new(int64)}

或者,可以使用更简洁的写法:

res := map[string]*interface{}{"id": 0, "name": "", "password": "", "add_time": 0}

这样,res["id"], res["name"]等元素就指向了实际的内存地址,scan函数就可以正确地将查询结果扫描到res中。 需要注意的是,new()函数返回的是一个指向新分配内存地址的指针,而直接赋值 0, "", 0 等会自动进行类型推断和指针转换。 这两种方法都能解决scan函数无法将结果集扫描到map的问题。