go数据库查询 unsupported Scan

使用go查询数据库时,有时候会遇到 **scan error sql: Scan error on column index XXXXX unsupported Scan, storing driver.Value type **这个错误,

这个错误产生的原因是,查询的结果中有的值是NULL , 导致在读查询结果时,遇到NUL 类型的数值,无法正确读出数值 现在通过一个简单的例子复现一下 先创建一个简单的表

1CREATE TABLE `user` (
2  `id` int(11) NOT NULL,
3  `name` varchar(255) DEFAULT NULL,
4  PRIMARY KEY (`id`)
5) ENGINE=InnoDB DEFAULT CHARSET=utf8;

其中 name这个字段默认是NULL 的,现在插入几条数据

1 insert into user(`id`,`name`) values(1,'A');
2 insert into user(`id`,`name`) values(2,'B');
3 insert into user(`id`,`name`) values(3,NULL);

go代码

 1package main
 2
 3import (
 4	"database/sql"
 5	"fmt"
 6	_ "github.com/go-sql-driver/mysql"
 7)
 8
 9type User struct {
10	id   uint32
11	name string
12}
13
14func main() {
15	db := Conn()
16	if db == nil {
17		return
18	}
19	result := make([]*User, 0, 10)
20	q := "SELECT `id`, `name` FROM `user`"
21	if rows, err := db.Query(q); err == nil {
22		for rows.Next() {
23			id := uint32(0)
24			name := ""
25			if err := rows.Scan(&id, &name); err == nil {
26				result = append(result, &User{
27					id:   id,
28					name: name,
29				})
30			} else {
31				fmt.Println("rows scan error", err)
32			}
33		}
34	} else {
35		fmt.Println("query error", err)
36	}
37	for _, v := range result {
38		fmt.Println(v)
39	}
40}
41
42func Conn() *sql.DB {
43	db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1)/go_test")
44	if err != nil {
45		fmt.Print("sql open error", err)
46		return nil
47	}
48	err2 := db.Ping()
49	if err2 != nil {
50		fmt.Print("sql pin error", err2)
51		return nil
52	}
53	return db
54}

运行后,报错

这个错误有两种解决办法

  1. 从数据层面解决,把name字段设置为非空字段,并且默认值设置为**""**空字符串,问题就解决了 改一下表
1CREATE TABLE `user` (
2  `id` int(11) NOT NULL,
3  `name` varchar(255) NOT NULL DEFAULT '',
4  PRIMARY KEY (`id`)
5) ENGINE=InnoDB DEFAULT CHARSET=utf8;

查询结果是正常的

对于一些特殊的查询,结果中难免会有NULL值,比如连接查询等等,这时候需要用第二种方式来解决 2. 使用go 提供的 sql.NullString类型值来结局,这个是string类型的, go 还提供了其他类型的,还有NullBoolbool类型的,NullFloat64float64类型的,NullInt64 int64类型的

为了方便,还是把表改回最开始,name默认是NULL类型的 修改一下代码

 1	result := make([]*User, 0, 10)
 2	q := "SELECT `id`, `name` FROM `user`"
 3	if rows, err := db.Query(q); err == nil {
 4		for rows.Next() {
 5			id := uint32(0)
 6			var name sql.NullString
 7			if err := rows.Scan(&id, &name); err == nil {
 8				u := &User{
 9					id: id,
10				}
11				if name.Valid {
12					u.name = name.String
13				} else {
14					u.name = ""
15				}
16				result = append(result, u)
17			} else {
18				fmt.Println("rows scan error", err)
19			}
20		}
21	} else {
22		fmt.Println("query error", err)
23	}

name 的类型改为 sql.NullString 并且在查询完成后,判断一下name是否有效

看一下结果

没有问题

到这问题解决了

发表了56篇文章 · 总计128.44k字
本博客已稳定运行
© QX
使用 Hugo 构建
主题 StackJimmy 设计