为了账号安全,请及时绑定邮箱和手机立即绑定

无法在 Mac OS X 上的 Go 1.5 中对超过 32768 字节的切片进行 gzip

无法在 Mac OS X 上的 Go 1.5 中对超过 32768 字节的切片进行 gzip

Go
函数式编程 2021-12-27 15:37:03
我正在尝试使用compress/gzip. 每当我在笔记本电脑上压缩长度超过 2^15 的切片时,解压后索引为 2^15 或更大的每个字节都设置为 0。当我在我的研究集群上运行相同的代码时,它也会中断。调用go version我的笔记本电脑打印:$ go versiongo version go1.5 darwin/amd64调用go version集群打印:$ go versiongo version go1.3.3 linux/amd64下面是我写的一个演示测试文件。它生成不同长度的随机切片,压缩它们,然后解压缩它们。它检查没有调用返回错误,并检查压缩和解压缩的切片是否相同:package compressimport (    "bytes"    "compress/gzip"    "math/rand"    "testing")func byteSliceEq(xs, ys []byte) bool {    if len(xs) != len(ys) { return false }    for i := range xs {        if xs[i] != ys[i] { return false }    }    return true}func TestGzip(t *testing.T) {    tests := []struct {        n int    }{        { 1<<10 },        { 1<<15 },        { 1<<15 + 1 },        { 1<<20 },    }    rand.Seed(0)    for i := range tests {        n := tests[i].n        in, out := make([]byte, n), make([]byte, n)        buf := &bytes.Buffer{}        for i := range in { in[i] = byte(rand.Intn(256)) }        writer := gzip.NewWriter(buf)        _, err := writer.Write(in)        if err != nil {            t.Errorf("%d) n = %d: writer.Write() error: %s",                i + 1, n, err.Error())        }        err = writer.Close()        if err != nil {            t.Errorf("%d) n = %d: writer.Close() error: %s",                i + 1, n, err.Error())        }        reader, err := gzip.NewReader(buf)        if err != nil {            t.Errorf("%d) n = %d: gzip.NewReader error: %s",                i + 1, n, err.Error())        }        reader.Read(out)        err = reader.Close()        if err != nil {            t.Errorf("%d) n = %d: reader.Close() error: %s",                i + 1, n, err.Error())        }当我运行这个测试时,我得到以下输出:$ go test --run "TestGzip"--- FAIL: TestGzip (0.12s)    gzip_test.go:77: 3) n = 32769: in[32768] = 78, but out[32768] = 0    gzip_test.go:77: 4) n = 1048576: in[32768] = 229, but out[32768] = 0FAILexit status 1有谁知道这里发生了什么?我是否以某种方式滥用了该软件包?如果我没有提供足够的信息,请告诉我。
查看完整描述

1 回答

?
慕丝7291255

TA贡献1859条经验 获得超6个赞

问题出在这一行:


reader.Read(out)

不能保证一步Reader.Read()读取整个out切片。


gzip.Reader.Read()是执行io.Reader.Read()。

引用其文档(“一般合同”):


Read(p []byte) (n int, err error)

Read 将最多len(p) 个字节读入 p。


不保证Reader.Read()会一直读取直到out被填满,如果实现需要,它可能会在更少的字节处停止(即使没有达到 EOF)。如果您传递“大”切片,则在实现的内部缓存耗尽时很容易发生这种情况。Read()返回读取的字节数(和error),您可以使用它来检查是否读取了完整的切片。


或者更好的是,您可以使用它io.ReadFull()来确保out已完全阅读:


if _, err = io.ReadFull(reader, out); err != nil {

    t.Errorf("Error reading full out slice:", err)

}

通过应用此更改,您的测试将通过。


查看完整回答
反对 回复 2021-12-27
  • 1 回答
  • 0 关注
  • 123 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信