前言
不知道各位在开发过程中有没有遇到表中字段值为Null,导致查询时会抛异常,遇到异常又是怎么处理的呢?下面分享一个我的处理的方法。
问题原因
表中字段的Null值在Go中对应的是nil,为什么查询返回赋予nil值会抛异常呢?我们看下官方文档对nil的说明:
nil是一个预先声明的标识符,表示指针、通道、函数、接口、map或切片类型的零值,类型必须是指针、通道、函数、接口、map或切片类型。
所以当我们在struct中用如string、int、time.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实现一个JSON的UnmarshalJSON方法
// 实现一个 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类型的处理方法,同理int、time.Time等类型处理亦是如此。
总结起来共四步:
- 定义类型别名
- 使用类型别名
- 实现JSON的MarshalJSON方法
- 实现JSON的UnmarshalJSON方法
如果你有更好的方案,欢迎评论区分享。