Go语言使用binary.Read读取二进制数据至切片返回空结果的问题排查
解决Go中binary.Read读取切片返回空的问题
这个问题我之前也踩过坑,核心原因是Go标准库encoding/binary包的Read函数处理切片的逻辑和你预期的不一样~
问题根源
你代码里的got := []int16{}是一个空切片,它的底层数组长度为0。binary.Read在处理切片时,只会读取足够的数据去填充切片现有的空间,不会自动为切片扩容或分配新的内存——因为它没办法知道你期望读取多少个元素,所以直接返回了空结果。
两种解决方案
方案一:提前知晓元素数量,初始化对应长度的切片
如果你明确知道要读取的int16元素个数,直接用make创建对应长度的切片即可:
r := bytes.NewReader(buf.Bytes()) // 初始化一个能容纳3个int16的切片 got := make([]int16, 3) if err := binary.Read(r, binary.LittleEndian, &got); err != nil { fmt.Println("binary.Read failed:", err) } fmt.Println("got:", got) // 输出 [1 2 3]
方案二:未知元素数量时,通过字节数计算元素个数
如果不确定要读取多少个元素,可以先根据reader的总字节数,结合int16的字节大小(固定2字节)计算出元素数量,再创建对应长度的切片:
r := bytes.NewReader(buf.Bytes()) // 计算可读取的int16元素总数:总字节数 / 单个int16的字节数 count := int(r.Size()) / binary.Size(int16(0)) got := make([]int16, count) if err := binary.Read(r, binary.LittleEndian, &got); err != nil { fmt.Println("binary.Read failed:", err) } fmt.Println("got:", got) // 输出 [1 2 3]
修正后的完整代码
package main import ( "bytes" "encoding/binary" "fmt" ) func main() { data := []int16{1, 2, 3} buf := new(bytes.Buffer) err := binary.Write(buf, binary.LittleEndian, data) if err != nil { fmt.Println("binary.Write failed:", err) } fmt.Println(buf.Bytes()) // 输出 [1 0 2 0 3 0] // 方案一实现 r1 := bytes.NewReader(buf.Bytes()) got1 := make([]int16, 3) if err := binary.Read(r1, binary.LittleEndian, &got1); err != nil { fmt.Println("binary.Read failed:", err) } fmt.Println("got1:", got1) // 方案二实现 r2 := bytes.NewReader(buf.Bytes()) count := int(r2.Size()) / binary.Size(int16(0)) got2 := make([]int16, count) if err := binary.Read(r2, binary.LittleEndian, &got2); err != nil { fmt.Println("binary.Read failed:", err) } fmt.Println("got2:", got2) }
补充说明
其实binary.Read的官方文档里已经明确了这个行为:当读取切片类型时,函数会读取切片长度对应的数据量来填充切片。如果切片是空的,自然就不会读取任何数据。所以一定要确保传入的切片有足够的空间来存储要读取的数据。
内容的提问来源于stack exchange,提问作者nos
相关产品推荐
相关产品推荐

