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

在 defer 中关闭 gzip writer 会导致数据丢失

在 defer 中关闭 gzip writer 会导致数据丢失

Go
素胚勾勒不出你 2022-05-23 16:56:34
我使用 golanggzip.NewWriter压缩切片,并defer Close()关闭 writer。但是当从压缩数据中读取时,它会返回unexpected EOF. 代码是:func main() {    a := []byte{'a', 'b', 'c', 'd', 'e', 'f'}    zippedData, err := zipData(a)    if err != nil {        panic(err)    }    unzippedData, err := unzipData(zippedData)    if err != nil {        panic(err)    }    fmt.Printf("%v\n", unzippedData)}压缩功能是:func zipData(originData []byte) ([]byte, error) {    var bf bytes.Buffer    gw := gzip.NewWriter(&bf)    defer gw.Close()    _, err := gw.Write(originData)    if err != nil {        return nil, errors.New(fmt.Sprintf("gzip data err: %v", err))    }    err = gw.Flush()    if err != nil {        return nil, err    }    // if I rm 'defer gw.Close()' and call 'gw.Close()' here, it'll be ok    logs.Debug("before gzip len: %v", len(originData))    logs.Debug("gzip len: %v", bf.Len())    return bf.Bytes(), nil}上面的 zip 函数用于defer gw.Close()关闭 gw。解压函数为:func unzipData(zippedData []byte) ([]byte, error) {    dst := make([]byte, len(zippedData))    copy(dst, zippedData)    reader, err := gzip.NewReader(bytes.NewBuffer(dst))    if err != nil {        return nil, errors.New(fmt.Sprintf("unzip err :%v", err))    }    defer reader.Close()    data, err := ioutil.ReadAll(reader)    if err != nil {        return nil, errors.New(fmt.Sprintf("read err :%v", err))    }    return data, err}为什么要defer gw.Close()案例unexpected EOF?
查看完整描述

2 回答

?
一只名叫tom的猫

TA贡献1906条经验 获得超3个赞

使用 defer,您会丢失 gzip 页脚。根据Close文档:

Close 通过将任何未写入的数据刷新到底层 io.Writer 并写入 GZIP 页脚来关闭 Writer。它不会关闭底层的 io.Writer。

因此,即使Flush刷新任何缓冲数据,它也不会写入页脚。通过延迟关闭,您将获得不包含页脚的字节数组并将其返回,然后将页脚写入输出。

在返回之前关闭 writer。


查看完整回答
反对 回复 2022-05-23
?
慕姐4208626

TA贡献1852条经验 获得超7个赞

With defer,在 return 语句中gw.Close()的调用之后运行。bf.Bytes()为了确保返回完整的内容,您应该gw.Close在尝试从缓冲区读取字节之前显式调用。

最简单的代码修复方法是将Flush调用替换为Close调用。Flush是在你没有写完的时候,但在你的情况下你已经完成了压缩,所以调用Close应该就足够了。



查看完整回答
反对 回复 2022-05-23
  • 2 回答
  • 0 关注
  • 167 浏览
慕课专栏
更多

添加回答

举报

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