boxmoe_header_banner_img

Hello! 欢迎来到悠悠畅享网!

文章导读

如何用Golang的compress库处理压缩 gzip/zlib实战案例


avatar
站长 2025年8月14日 1

go语言中compress/gzip和compress/zlib均基于deflate算法,gzip适用于文件和http压缩,因包含头部和校验信息,而zlib更轻量,适合协议传输;通过newwriter压缩数据并需调用close刷新,newreader解压后也需close释放资源;可实现http中间件自动压缩响应体,或读写.gz文件用于日志归档;两者api相似,但封装格式不同,gzip多用于存储,zlib用于体积敏感场景,正确使用可有效减少传输体积,完整掌握后可用于多种实际场景。

如何用Golang的compress库处理压缩 gzip/zlib实战案例

Go语言标准库中的

compress

包提供了对多种压缩格式的支持,其中

gzip

zlib

是最常用的两种。它们都基于 DEFLATE 算法,但在封装格式和用途上略有不同。本文通过几个实用案例,带你掌握如何在实际项目中使用 Golang 的

compress/gzip

compress/zlib

库。


1. 使用

compress/gzip

压缩和解压数据

gzip

常用于 HTTP 响应压缩、文件压缩(如

.gz

文件)等场景。

压缩字符串为 gzip 数据

package main  import (     "bytes"     "compress/gzip"     "fmt"     "io" )  func compressGzip(data string) ([]byte, error) {     var buf bytes.Buffer     writer := gzip.NewWriter(&buf)     _, err := io.WriteString(writer, data)     if err != nil {         return nil, err     }     if err := writer.Close(); err != nil {         return nil, err     }     return buf.Bytes(), nil }  func main() {     original := "Hello, this is a test string for gzip compression."     compressed, err := compressGzip(original)     if err != nil {         panic(err)     }     fmt.Printf("Original: %d bytesn", len(original))     fmt.Printf("Compressed: %d bytesn", len(compressed)) }

解压 gzip 数据

func decompressGzip(data []byte) (string, error) {     reader, err := gzip.NewReader(bytes.NewReader(data))     if err != nil {         return "", err     }     defer reader.Close()     var buf bytes.Buffer     _, err = io.Copy(&buf, reader)     if err != nil {         return "", err     }     return buf.String(), nil }

main

中调用:

立即学习go语言免费学习笔记(深入)”;

decompressed, err := decompressGzip(compressed) if err != nil {     panic(err) } fmt.Printf("Decompressed: %sn", decompressed)

注意:gzip.NewReader 必须调用 Close() 释放内部资源,即使只读取一次。


2. 使用

compress/zlib

进行轻量级压缩

zlib

格式比

gzip

更轻,常用于协议传输、数据库存储等对体积敏感但不需要文件头信息的场景。

压缩数据为 zlib 格式

import "compress/zlib"  func compressZlib(data string) ([]byte, error) {     var buf bytes.Buffer     writer := zlib.NewWriter(&buf)     _, err := io.WriteString(writer, data)     if err != nil {         return nil, err     }     if err := writer.Close(); err != nil {         return nil, err     }     return buf.Bytes(), nil }

解压 zlib 数据

func decompressZlib(data []byte) (string, error) {     reader, err := zlib.NewReader(bytes.NewReader(data))     if err != nil {         return "", err     }     defer reader.Close()     var buf bytes.Buffer     _, err = io.Copy(&buf, reader)     if err != nil {         return "", err     }     return buf.String(), nil }

用法与

gzip

类似,只是换用了

zlib

包。


3. 实战:HTTP 中间件支持 gzip 压缩响应

在 Web 服务中,我们可以使用

gzip

来压缩响应体,减少传输体积。

package main  import (     "compress/gzip"     "net/http" )  type gzipResponseWriter struct {     http.ResponseWriter     *gzip.Writer }  func (w gzipResponseWriter) Write(data []byte) (int, error) {     return w.Writer.Write(data) }  func gzipMiddleware(next http.Handler) http.Handler {     return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {         if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {             next.ServeHTTP(w, r)             return         }          writer := gzip.NewWriter(w)         defer writer.Close()          w.Header().Set("Content-Encoding", "gzip")         w.Header().Set("Vary", "Accept-Encoding")          gzResp := gzipResponseWriter{ResponseWriter: w, Writer: writer}         next.ServeHTTP(gzResp, r)     }) }  func handler(w http.ResponseWriter, r *http.Request) {     w.Write([]byte("This is a large response that will be compressed with gzip.")) }  func main() {     mux := http.NewServeMux()     mux.HandleFunc("/", handler)     http.ListenAndServe(":8080", gzipMiddleware(mux)) }

这个中间件检查客户端是否支持

gzip

,如果支持,则包装

ResponseWriter

并设置编码头。


4. 处理

.gz

文件:读写压缩文件

Go 可以直接读写

.gz

文件,适合处理日志归档等场景。

写入 gzip 文件

import (     "os"     "compress/gzip" )  func writeGzipFile(filename, content string) error {     file, err := os.Create(filename)     if err != nil {         return err     }     defer file.Close()      gz := gzip.NewWriter(file)     defer gz.Close()      _, err = gz.Write([]byte(content))     return err }

读取 gzip 文件

func readGzipFile(filename string) (string, error) {     file, err := os.Open(filename)     if err != nil {         return "", err     }     defer file.Close()      gz, err := gzip.NewReader(file)     if err != nil {         return "", err     }     defer gz.Close()      content, err := io.ReadAll(gz)     return string(content), err }

小结关键点

  • gzip

    zlib

    都使用

    NewWriter

    NewReader

    ,API 高度相似。

  • 压缩后必须调用
    Close()

    触发 flush,否则数据不完整。

  • gzip.NewReader

    zlib.NewReader

    返回的 reader 必须

    Close()

  • gzip

    包含文件头和校验和,适合文件存储;

    zlib

    更紧凑,适合嵌入协议。

  • 在 HTTP 服务中启用压缩可显著减少带宽。

基本上就这些。掌握这几个模式后,你可以灵活应用于日志压缩、API 响应、配置传输等场景。



评论(已关闭)

评论已关闭