Go如何优雅的处理表中字段值为Null的情况

981 阅读2分钟

前言

不知道各位在开发过程中有没有遇到表中字段值为Null,导致查询时会抛异常,遇到异常又是怎么处理的呢?下面分享一个我的处理的方法。

问题原因

表中字段的Null值在Go中对应的是nil,为什么查询返回赋予nil值会抛异常呢?我们看下官方文档对nil的说明:

nil是一个预先声明的标识符,表示指针、通道、函数、接口、map或切片类型的零值,类型必须是指针、通道、函数、接口、map或切片类型。

所以当我们在struct中用如stringinttime.Time等类型去接收时,当然会抛异常啦

解决方案

// 定义sql.NullString的别名为NullString
type NullString sql.NullString
​
type Login struct {
    Name     NullString // 使用类型别名NullString
}
// 实现一个JSON的MarshalJSON 方法
func (n *NullString) MarshalJSON() ([]byte, error) {
    ns := n.String
    return []byte(fmt.Sprintf("\"%s\"", ns)), nil
}

以上方法就能很好解决查询字段值为 Null 时,抛出异常的问题了。

但是又有新的问题出现了,用类型别名 NullString 代替string类型,此时用Login结构体接收前端提交过来的数据,会抛出(*UnmarshalTypeError).Error异常,根据异常信息可以看出应该是在反序列化时 JSON 属性类型与 struct 的不同,导致抛出异常。

既然是反序列化时导致抛出异常的,那我们就以NullString实现一个JSONUnmarshalJSON方法

// 实现一个 JSON的UnmarshalJSON方法
func (n *NullString) UnmarshalJSON(b []byte) error {
   return json.Unmarshal(b, &n.String)
}

此时完美解决问题

附完整代码

// 定义sql.NullString的别名为NullString
type NullString sql.NullString
​
type Login struct {
    Name     NullString // 使用类型别名NullString
}
// 实现一个 JSON的MarshalJSON方法,用来解决查询返回null抛异常问题
func (n *NullString) MarshalJSON() ([]byte, error) {
    ns := n.String
    return []byte(fmt.Sprintf("\"%s\"", ns)), nil
}
​
// 实现一个 JSON的UnmarshalJSON方法,用来解决接收前端参数抛异常的问题
func (n *NullString) UnmarshalJSON(b []byte) error {
   return json.Unmarshal(b, &n.String)
}

以上是对string类型的处理方法,同理inttime.Time等类型处理亦是如此。 总结起来共四步:

  1. 定义类型别名
  2. 使用类型别名
  3. 实现JSON的MarshalJSON方法
  4. 实现JSON的UnmarshalJSON方法

如果你有更好的方案,欢迎评论区分享。