クロージャを延期すると gzip Writer でデータが失われる
Go で gzip.NewWriter を利用してバイト スライスを圧縮すると、一般的に次のことが観察されます。ライターの終了を延期すると、データが失われます。この現象は、予期しないファイルの終わり (EOF) エラーで途中で終了するため、圧縮データを読み取るときに顕著になります。
これを理解するために、提供されているコード スニペットを調べてみましょう。
<code class="go">func zipData(originData []byte) ([]byte, error) { // Create a buffer to store the compressed data var bf bytes.Buffer // Initialize the gzip writer with the buffer gw := gzip.NewWriter(&bf) // Defer closure of the writer defer gw.Close() // Write the original data to the writer _, err := gw.Write(originData) if err != nil { return nil, err } // Flush the writer to write any buffered data if err = gw.Flush(); err != nil { return nil, err } // Return the compressed data return bf.Bytes(), nil }</code>
この問題は、gzip ライター (gw) を閉じるために defer を使用することに起因します。 Close() のドキュメントによると:
「Close は、書き込まれていないデータを基になる io.Writer にフラッシュし、GZIP フッターを書き込むことによって Writer を閉じます。」
この場合、遅延されたクロージャは、関数がバッファ (bf) に格納された圧縮データを返した後に実行されます。ただし、フッターは Close() メソッドが呼び出されるまで書き込まれず、圧縮データが返されるときに不完全なままになります。
この問題は、圧縮データを返す前にライターを手動で閉じることで解決できます。
<code class="go">func zipData(originData []byte) ([]byte, error) { // ... (same code as before) ... // Close the writer to write the footer if err := gw.Close(); err != nil { return nil, err } // Return the compressed data return bf.Bytes(), nil }</code>
戻る前にライターを閉じると、GZIP フッターが正常に書き込まれ、EOF エラーが発生することなく圧縮データを読み取ることができます。
以上がgzip.NewWriter の終了を延期すると Go でデータ損失が発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。