有如下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也行啊。這樣至少能快速定位錯誤吧。否則對於不習慣看文檔,只是看一下方法的聲明就想快速使用的人,這種坑掉進去要爬出來是頗費一些工夫的。