NULL值处理
简单说就是设计数据库的时候不要出现null,处理起来非常费力。Null的type很有限,例如没有sql.NullUint64
; null值没有默认零值。
for rows.Next() { var s sql.NullString err := rows.Scan(&s) // check err if s.Valid { // use s.String } else { // NULL value } }
https://segmentfault.com/a/1190000003036452
------------
而对于在Go中构建页面, text/template
中的很多功能不会自动判断Nullable类型,比如 {{if .Property}}
,如果 Property
属性是Nullable类型,且他是 NULL
即 Valid
属性为 false
,但是模板中的 if
还是会认为 true
,因为这个Nullable类型本身是一个值所以 if
会认为是 true
,而Nullable类型本身到底是不是 NULL
根本没有意义,所以必须要写 {{if .Property.Valid}}
。在输出上,也要写 {{.Property.String}}
(不同Nullable类型值得属性会不一样,这里以 sql.NullString
演示)。
或者用实际代码演示这个问题:
package main import ( "bytes" "database/sql" "fmt" "text/template" ) type Test struct { EmptyString sql.NullString NonEmptyString sql.NullString } func main() { test := &Test{} test.EmptyString = sql.NullString{Valid: false} test.NonEmptyString = sql.NullString{Valid: true, String: "Mgen"} template := template.Must(template.New("test").Parse("{{if .EmptyString}}{{.NonEmptyString}}{{end}}")) buffer := &bytes.Buffer{} err := template.Execute(buffer, test) if err != nil { panic(err) } fmt.Print(buffer.String()) }
这段代码会输出:
{Mgen true}
验证了上面讲的两个问题:
- 为
NULL
的Nullable类型会在模板if
中直接理解成true
. - 输出问题,上面输出
{Mgen true}
实际上就是把sql.NullString
的两个内部属性全部输出出来了。
Go中 NullString
类型定义:
type NullString struct { String string Valid bool // Valid is true if String is not NULL }
所以正确的模板应该这样写:
template := template.Must(template.New("test").Parse("{{if .EmptyString.Valid}}{{.NonEmptyString.String}}{{end}}"))
总之一旦遇到数据库中的 NULL
,还是会稍微有些麻烦的,目前的解决方案可供选择:
- 数据库中尽量不存
NULL
值,或者使用ISNULL
或COALESCE
对NULL
值坐下处理。 - JSON上对Nullable类型进行改造,模板定义上属性要针对Nullable类型的属性做判断。
- 不需要Nullable,
NULL
值转换成空值, 这是文章开头我说的愿望:joy:,目前不支持 。
http://www.tuicool.com/articles/QJZJjaQ