使用标准数据库/ sql Row.Scan()
我在行中遇到空值问题。如果不考虑连续可能的空值,我可能会得到像<nil> -> *string
这样的扫描错误。这很常见,使用LEFT JOIN查询或缺少NO NULL列约束的弱定义表。
有sql.NullXXX
种类型(例如sql.NullInt64)可用于扫描行中可能的空值,然后检查值是否为.Valid
。但是,这些类型不实现JSON编组,需要更多的逻辑和编码。
要解决这个问题,是否可以更好地处理SQL查询中的COALESCE()
列值,或者在golang代码中执行一些额外的编码?
答案 0 :(得分:2)
作为一个选项,您可以实现与JSON Marshaler界面匹配的自定义数据类型。之后,您将能够使用常规标签封送您的结构。
检查示例:
type UserTitleType sql.NullString
func (s UserTitleType) MarshalJSON() ([]byte, error) {
if s.Valid {
return json.Marshal(s.String)
}
return jsonNull, nil
}
type User struct {
Id int64 `json:"id"`
Title UserTitleType `json:"title"`
}
答案 1 :(得分:1)
您可以对sql包提供的类型使用别名,例如(NullInt64,NullString等...)。使用它有两个好处,一个可以扫描空值,可以使用golang结构,第二个可以用JSON编组该结构。
请查看示例代码:
// NullInt64 is an alias for sql.NullInt64 data type
type NullInt64 sql.NullInt64
// Scan implements the Scanner interface for NullInt64
func (ni *NullInt64) Scan(value interface{}) error {
var i sql.NullInt64
if err := i.Scan(value); err != nil {
return err
}
// if nil the make Valid false
if reflect.TypeOf(value) == nil {
*ni = NullInt64{i.Int64, false}
} else {
*ni = NullInt64{i.Int64, true}
}
return nil
}
// MarshalJSON for NullInt64
func (ni *NullInt64) MarshalJSON() ([]byte, error) {
if !ni.Valid {
return []byte("null"), nil
}
return json.Marshal(ni.Int64)
}
请看一下这个article,在golang中处理空值以及如何在JSON中使用它会非常有用。
答案 2 :(得分:0)
// Scan implements the Scanner interface.
func (n *NullInt64) Scan(value interface{}) error {
var ok bool
if value == nil {
n.Int64, n.Valid = 0, false
return nil
}
n.Valid = true
n.Int64, ok = value.(int64)
if !ok {
return errors.New("convert error")
}
return nil
}
// Value implements the driver Valuer interface.
func (n NullInt64) Value() (driver.Value, error) {
if !n.Valid {
return nil, nil
}
return n.Int64, nil
}