Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 关闭延迟中的gzip写入程序会导致数据丢失_Go - Fatal编程技术网

Go 关闭延迟中的gzip写入程序会导致数据丢失

Go 关闭延迟中的gzip写入程序会导致数据丢失,go,Go,我使用golanggzip.NewWriter压缩一个片段,并使用延迟关闭()关闭编写器。但是从压缩数据读取时,它将返回意外的EOF。代码是: func main() { a := []byte{'a', 'b', 'c', 'd', 'e', 'f'} zippedData, err := zipData(a) if err != nil { panic(err) } unzippedData, err := unzipData(zi

我使用golang
gzip.NewWriter
压缩一个片段,并使用
延迟关闭()
关闭编写器。但是从压缩数据读取时,它将返回
意外的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)

}


zip函数是:

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
}


为什么
延迟gw.Close()
案例
意外EOF

使用defer时,您缺少gzip页脚。根据
关闭
文档:

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

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


返回前关闭编写器。

使用“延迟”,您将丢失gzip页脚。根据
关闭
文档:

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

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


在返回之前关闭编写器。

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


最简单的代码修复方法是将
Flush
调用替换为
Close
调用
Flush
用于您尚未完成编写,但您已经完成压缩,因此调用
Close
就足够了。

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

最简单的代码修复方法是将
Flush
调用替换为
Close
调用
Flush
用于您尚未完成编写,但您已经完成压缩,因此调用
Close
就足够了