我使用 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。

慕姐4208626
TA貢獻1852條經驗 獲得超7個贊
With defer
,在 return 語句中gw.Close()
的調用之后運行。bf.Bytes()
為了確保返回完整的內容,您應該gw.Close
在嘗試從緩沖區讀取字節之前顯式調用。
最簡單的代碼修復方法是將Flush
調用替換為Close
調用。Flush
是在你沒有寫完的時候,但在你的情況下你已經完成了壓縮,所以調用Close
應該就足夠了。
- 2 回答
- 0 關注
- 188 瀏覽
添加回答
舉報
0/150
提交
取消