在 Go 專案處理空值日期

做法

在一些情況下,資料庫裡的日期欄位會是 NULL,比方說 ReviewedAt 欄位,如果有值,表示「已審核」,如果為 NULL,表示「未審核」。

1
2
3
type Model struct {
ReviewedAt ReviewedAt
}

這裡的 ReviewedAt 如果是 time.Time 型別:

1
type ReviewedAt time.Time

ReviewedAt 欄位為 NULL,且序列化成 JSON 格式時,日期會變成預設值。

1
2
3
{
"ReviewedAt": "0001-01-01T00:00:00Z"
}

標準庫 database/sql 有提供 sql.NullTime 型別可以做為替代方案,如下:

1
type ReviewedAt sql.NullTime

sql.NullTime 型別包含了 TimeValid 屬性:

1
2
3
4
type NullTime struct {
Time time.Time
Valid bool // Valid is true if Time is not NULL
}

不過,當 ReviewedAt 欄位為 NULL,且序列化成 JSON 格式時,日期會變成以下物件:

1
2
3
4
5
{
"ReviewedAt": {
"Time": "0001-01-01T00:00:00Z",
"Valid": false
}

因此需要進一步封裝 sql.NullTime 型別:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package model

import (
"database/sql"
"encoding/json"
)

type NullTime struct {
sql.NullTime
}

func (v *NullTime) MarshalJSON() ([]byte, error) {
if v.Valid {
return json.Marshal(v.Time)
}
return json.Marshal(nil)
}

在模型中使用封裝後的 NullTime 型別:

1
2
3
type Model struct {
ReviewedAt NullTime
}

現在,當 ReviewedAt 欄位為 NULL,且序列化成 JSON 格式時,日期就可以顯示為 NULL

1
2
3
{
"ReviewedAt": null
}