Go十大常見錯誤第一篇:未知列舉值

coding進階發表於2022-06-05

前言

這是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

知乎:無忌

References

相關文章