前言
這是Go十大常見錯誤系列的第一篇:未知列舉值。素材來源於Go佈道者,現Docker公司資深工程師Teiva Harsanyi。
本文涉及的原始碼全部開源在:Go十大常見錯誤原始碼,歡迎大家關注公眾號,及時獲取本系列最新更新。
場景
讓我們來看下面的程式碼示例:
type Status uint32
const (
StatusOpen Status = iota
StatusClosed
StatusUnknown
)
這裡我們使用iota
定義了一個列舉,對應的列舉值分別是:
StatusOpen = 0
StatusClosed = 1
StatusUnknown = 2
假設我們業務程式碼裡的資料結構包含了列舉型別,比如下例:
type Request struct {
ID int `json:"Id"`
Timestamp int `json:"Timestamp"`
Status Status `json:"Status"`
}
我們要把接受到的JSON請求反序列化為Request
結構體型別。
{
"Id": 1234,
"Timestamp": 1563362390,
"Status": 0
}
對於上面這個JSON請求資料,Request
結構體裡的Status
欄位會被解析為0,對應的是StatusOpen
,符合預期。
但是如果由於各種原因沒有傳Status
欄位,對於如下的JSON請求
{
"Id": 1235,
"Timestamp": 1563362390
}
在將這個JSON請求反序列化為Request
結構體型別的時候,因為JSON串裡沒有Status
欄位,因此Request
結構體裡的Status
欄位的值會是零值,也就是uint32
的零值0。這個時候Status
欄位的值還是StatusOpen
,而不是我們預期的StatusUnknown
。
最佳實踐
因此對於列舉值的最佳實踐,是把列舉的未知值設定為0。
type Status uint32
const (
StatusUnknown Status = iota
StatusOpen
StatusClosed
)
這樣設計後,如果JSON請求裡沒有傳Status
欄位,那反序列化後的Request
結構體裡的Status
欄位的值就是StatusUnknown
,符合預期。
開源地址
文章和示例程式碼開源在GitHub: Go語言初級、中級和高階教程。
公眾號:coding進階。關注公眾號可以獲取最新Go面試題和技術棧。
個人網站:Jincheng's Blog。
知乎:無忌。