binary.Write 小坑一個兼論go的錯誤處理哲學

有如下go代碼:

const (
 foo = 123
)
buffer := new(bytes.Buffer)
binary.Write(buffer, binary.BigEndian, foo)
fmt.Println(buffer.Len())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

輸出結果是0,foo沒有寫入到buffer中。原因在於,binary包的Write內部調用了intDataSize函數獲取foo的長度:

func intDataSize(data interface{}) int {
    switch data := data.(type) {
    case bool, int8, uint8, *bool, *int8, *uint8:
        return 1
    case []int8:
        return len(data)
    case []uint8:
        return len(data)
    case int16, uint16, *int16, *uint16:
        return 2
    case []int16:
        return 2 * len(data)
    case []uint16:
        return 2 * len(data)
    case int32, uint32, *int32, *uint32:
        return 4
    case []int32:
        return 4 * len(data)
    case []uint32:
        return 4 * len(data)
    case int64, uint64, *int64, *uint64:
        return 8
    case []int64:
        return 8 * len(data)
    case []uint64:
        return 8 * len(data)
    }
    return 0
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

而foo的類型是int,intDataSize函數不處理int類型,因此返回0。導致沒有數據被寫入。 
當然,這是我用錯了,因爲binary包的文檔裏面寫了:

Numbers are translated by reading and writing fixed-size values. 
A fixed-size value is either a fixed-size arithmetic 
type (bool, int8, uint8, int16, float32, complex64, …) 
or an array or struct containing only fixed-size values.

也就是說,使用binary包時,必須使用明確的長度確定的類型,可以用int32,但別用int。 
沒看清除文檔,用錯了,怨不得別人。但是binary包把錯誤直接吞掉的做法,似乎和go的錯誤處理哲學背離了啊。 
intDataSize 函數對於他不能處理的類型,難道不能返回一個error麼?或者粗暴些直接給個panic也行啊。這樣至少能快速定位錯誤吧。否則對於不習慣看文檔,只是看一下方法的聲明就想快速使用的人,這種坑掉進去要爬出來是頗費一些工夫的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章