You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现database/sql.Scanner接口适配数据库查询字段?

实现database/sql.Scanner接口的正确方式

问题根源

你已经正确实现了database/sql.Scanner接口,但调用代码存在两个核心错误:

  1. cols切片里存的是类型本身(Type_int、Type_string),而非这些类型的实例指针——rows.Scan需要接收实现了Scanner接口的类型指针,才能触发Scan方法修改实例值。
  2. 后续对ptr[i]做*any类型断言完全错误,因为cols[i]的实际类型是你定义的自定义类型,不是any。

修复后的完整代码

自定义类型实现(无需修改)

import "fmt"

type Type_int int

func (t *Type_int) Scan(value interface{}) error {
    switch value := value.(type) {
    case int64:
        *t = Type_int(value)
    default:
        return fmt.Errorf("Invalid database type: %T %v", value, value)
    }
    return nil
}

type Type_string string

func (t *Type_string) Scan(value interface{}) error {
    switch value := value.(type) {
    case []uint8:
        *t = Type_string(value)
    default:
        return fmt.Errorf("Invalid database type: %T %v", value, value)
    }
    return nil
}

静态列场景的调用代码

如果列数量和类型固定,直接创建实例指针传入即可:

// 初始化自定义类型实例
var id Type_int
var isSuspended Type_int
var name Type_string

// 准备Scanner接口指针切片
ptr := []interface{}{&id, &isSuspended, &name}

if err := rows.Scan(ptr...); err != nil {
    fmt.Println("err:", err)
    return
}

// 映射列名到结果
res := make(map[string]any)
res_cols := []string{"id", "is_suspended", "name"} // 假设这是查询返回的列名列表

res[res_cols[0]] = id
res[res_cols[1]] = isSuspended
res[res_cols[2]] = name

// 打印结果
for k, v := range res {
    fmt.Printf("Type: %T %s\n", v, k)
}

动态列场景的调用代码

如果列数量或类型不固定,用反射动态生成实例指针:

import "reflect"

// 定义列对应的类型列表
colTypes := []reflect.Type{
    reflect.TypeOf(Type_int(0)),
    reflect.TypeOf(Type_int(0)),
    reflect.TypeOf(Type_string("")),
}
ptr := make([]interface{}, len(colTypes))

for i, t := range colTypes {
    // 创建类型零值实例并取地址
    ptr[i] = reflect.New(t).Interface()
}

if err := rows.Scan(ptr...); err != nil {
    fmt.Println("err:", err)
    return
}

// 提取结果到map
res := make(map[string]any)
for i, name := range res_cols {
    // 获取实例的实际值
    res[name] = reflect.ValueOf(ptr[i]).Elem().Interface()
    fmt.Printf("Type: %T %s\n", res[name], name)
}

内容的提问来源于stack exchange,提问作者clarkk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:15:23