如果你在Golang中处理过SQL,你就会知道处理NULL
值并不容易。database/sql
接口已经通过使用Go
的nil
来支持NULL
值,但语言的设计不允许将nil
分配给string
或int
变量。在这篇文章中,我将告诉你一些方法。
1) 指针
在Go
中,如果原始变量不是一个指针,就不能赋值为nil
。指针通常用于将共享数据传递给另一个函数,以使内存的使用更加有效,但我们也有另一个很好的理由来使用它:处理NULL
值。
type User struct {
id int64
name *string
age *int32
}
err := db.QueryRow("SELECT NULL, 2").Scan(&, &u.Age)
在这种情况下,我们可以将Name
字段设置为其指针的nil
。sql.Scan()
通过将给定的指针参数设置为nil
来处理NULL
值。json.Marshall()
操作也支持在JSON
格式中设置nil
指针为null
。但每次使用变量或结构字段作为指针时,你必须检查这些指针是否为空。如果u.Age
是nil
,那么你引用它,程序将崩溃。
2) sql.Null*
在sql
包中定义了一些结构。它允许使用不同原始类型的变量,这些变量可以是null
的。这些结构还实现了一个扫描器和一个值接口,允许在sql
操作中使用。但它默认不处理JSON
格式的数据,所以你必须自己实现。文档
type User struct {
id int64
name sql.NullString
age sql.NullInt32
}
err := db.QueryRow("SELECT 'Ekin', NULL").Scan(&, &u.Age)
例如,我们看sql.NullString
结构,它有两个字段,分别是String
和Valid
。对于非NULL
值,.Valid
字段将等于true
,.String
等于 Ekin
。否则,.Valid
将为假,.String
将为""。如果你的字段类型是NullString
,首先你必须检查这个变量的Valid
字段。如果是有效的,我们可以通过.String
字段获得值。
3) /guregu/null
这是第三种方法,来自Github的一个外部包,用于处理NULL
值,与第二种方法非常相似。但它更容易创建nullable
类型。它还支持JSON
的marshall
操作。文档
4) 使用COALESCE函数
COALESCE
是大多数关系型数据库系统(SQLite、PostgreSQL、MySQL、SQL Server和Oracle)中的SQL
函数。这个函数根据其给定的参数,尝试返回第一个非空值。文档
type User struct {
id int64
name string
age int32
}
err := db.QueryRow("SELECT COALESCE(NULL, '')").Scan(&)
5) 不要使用NULL值
是的,这不是一个程序化的解决方案,但我们可以通过不使用NULL
值来避免查询的NULL
返回。通常情况下,NULL
值来自于列的默认值,或者我们将值设置为NULL
。所以,如果我们不使用NULL
值,我们就不需要处理它。😎
但这并不意味着我们不应该使用NULL
。它有时是必要的,有时不是。我建议你自己决定。