插件窝 干货文章 Go语言db.QueryRow().Scan如何将数据库查询结果映射到map中?

Go语言db.QueryRow().Scan如何将数据库查询结果映射到map中?

列名 查询 结果 interface 612    来源:    2025-03-13

在Go语言中,db.QueryRow().Scan() 通常用于将查询结果映射到结构体或单独的变量中。如果你想将查询结果映射到 map 中,你需要手动处理这个过程。以下是一个示例,展示了如何将查询结果映射到 map[string]interface{} 中。

假设你有一个数据库表 users,表结构如下:

CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    age INT,
    email VARCHAR(100)
);

你可以使用以下代码将查询结果映射到 map[string]interface{} 中:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql" // 导入MySQL驱动
)

func main() {
    // 打开数据库连接
    db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname")
    if err != nil {
        panic(err)
    }
    defer db.Close()

    // 查询单行数据
    var id int
    var name string
    var age int
    var email string

    row := db.QueryRow("SELECT id, name, age, email FROM users WHERE id = ?", 1)
    err = row.Scan(&id, &name, &age, &email)
    if err != nil {
        if err == sql.ErrNoRows {
            fmt.Println("No rows found")
        } else {
            panic(err)
        }
    }

    // 将查询结果映射到map中
    resultMap := map[string]interface{}{
        "id":    id,
        "name":  name,
        "age":   age,
        "email": email,
    }

    // 打印map
    fmt.Println(resultMap)
}

解释:

  1. db.QueryRow(): 用于查询单行数据。
  2. row.Scan(): 将查询结果扫描到变量中。
  3. map[string]interface{}: 用于存储查询结果,键是列名,值是对应的数据。

动态列名的情况

如果你不知道查询的列名,或者列名是动态的,你可以使用 rows.Columns() 来获取列名,然后动态地将结果映射到 map 中。以下是一个示例:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql" // 导入MySQL驱动
)

func main() {
    // 打开数据库连接
    db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/dbname")
    if err != nil {
        panic(err)
    }
    defer db.Close()

    // 查询单行数据
    rows, err := db.Query("SELECT id, name, age, email FROM users WHERE id = ?", 1)
    if err != nil {
        panic(err)
    }
    defer rows.Close()

    // 获取列名
    columns, err := rows.Columns()
    if err != nil {
        panic(err)
    }

    // 创建一个切片来存储列的值
    values := make([]interface{}, len(columns))
    for i := range values {
        values[i] = new(interface{})
    }

    // 将查询结果映射到map中
    resultMap := make(map[string]interface{})
    if rows.Next() {
        err = rows.Scan(values...)
        if err != nil {
            panic(err)
        }

        for i, col := range columns {
            resultMap[col] = *(values[i].(*interface{}))
        }
    }

    // 打印map
    fmt.Println(resultMap)
}

解释:

  1. rows.Columns(): 获取查询结果的列名。
  2. values := make([]interface{}, len(columns)): 创建一个切片来存储列的值。
  3. rows.Scan(values...): 将查询结果扫描到 values 切片中。
  4. resultMap[col] = *(values[i].(*interface{})): 将列名和对应的值存储到 map 中。

这种方法可以处理动态列名的情况,适用于你不知道查询结果的列名或列名是动态生成的场景。