在Golang开发中,网络传输的数据量过大会导致请求响应速度变慢、带宽成本上升,使用gzip压缩可以有效减少传输数据体积。Golang标准库自带的compress/gzip包提供了完整的gzip压缩与解压能力,同时可以结合net/http包实现HTTP请求级别的压缩处理。

Golang gzip基础压缩与解压实现
基础数据压缩
使用compress/gzip包实现基础数据压缩,核心是通过gzip.NewWriter创建压缩写入器,将数据写入后完成压缩。以下是字符串数据压缩的示例:
package main
import (
"bytes"
"compress/gzip"
"fmt"
)
// 压缩字符串数据
func compressData(data string) ([]byte, error) {
var buf bytes.Buffer
// 创建gzip压缩写入器
gz := gzip.NewWriter(&buf)
// 写入待压缩数据
_, err := gz.Write([]byte(data))
if err != nil {
return nil, err
}
// 关闭写入器,确保压缩数据完整写入缓冲区
err = gz.Close()
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func main() {
originData := "这是一段需要压缩的测试数据,压缩后体积会明显减小,适合网络传输场景"
compressed, err := compressData(originData)
if err != nil {
fmt.Println("压缩失败:", err)
return
}
fmt.Printf("原始数据长度: %d, 压缩后长度: %dn", len(originData), len(compressed))
}
基础数据解压
解压是压缩的逆过程,通过gzip.NewReader创建解压读取器,读取压缩数据即可还原原始内容:
package main
import (
"bytes"
"compress/gzip"
"fmt"
)
// 解压gzip数据
func decompressData(compressedData []byte) (string, error) {
// 创建压缩数据的读取器
reader, err := gzip.NewReader(bytes.NewReader(compressedData))
if err != nil {
return "", err
}
defer reader.Close()
// 读取解压后的数据
var result bytes.Buffer
_, err = result.ReadFrom(reader)
if err != nil {
return "", err
}
return result.String(), nil
}
func main() {
originData := "这是一段需要压缩的测试数据,压缩后体积会明显减小,适合网络传输场景"
// 先压缩再解压测试
compressed, _ := compressData(originData)
decompressed, err := decompressData(compressed)
if err != nil {
fmt.Println("解压失败:", err)
return
}
fmt.Println("解压后数据:", decompressed)
}
HTTP请求压缩实现
HTTP服务端返回压缩响应
HTTP服务端可以在响应头中添加Content-Encoding: gzip,同时将响应体进行gzip压缩,告知客户端需要解压处理。以下是简单的HTTP服务端实现:
package main
import (
"compress/gzip"
"fmt"
"io"
"net/http"
"strings"
)
// 自定义响应写入器,包装gzip写入器
type gzipResponseWriter struct {
io.Writer
http.ResponseWriter
}
func (w gzipResponseWriter) Write(data []byte) (int, error) {
return w.Writer.Write(data)
}
// gzip中间件,对响应进行压缩
func gzipMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 检查客户端是否支持gzip
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
next(w, r)
return
}
// 设置响应头告知客户端内容已压缩
w.Header().Set("Content-Encoding", "gzip")
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
// 创建gzip写入器
gz := gzip.NewWriter(w)
defer gz.Close()
// 包装响应写入器
gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w}
next(gzw, r)
}
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
// 返回大量测试数据,方便观察压缩效果
longData := "Hello Golang Gzip " + strings.Repeat("test data ", 1000)
fmt.Fprint(w, longData)
}
func main() {
http.HandleFunc("/hello", gzipMiddleware(helloHandler))
fmt.Println("服务启动在 :8080")
http.ListenAndServe(":8080", nil)
}
HTTP客户端发送压缩请求
HTTP客户端可以在请求头中添加Content-Encoding: gzip,同时将请求体进行gzip压缩后发送,服务端接收到后需要先解压再处理。以下是客户端实现示例:
package main
import (
"bytes"
"compress/gzip"
"fmt"
"io"
"net/http"
)
// 发送gzip压缩的POST请求
func sendGzipRequest(url string, data string) error {
// 压缩请求数据
var buf bytes.Buffer
gz := gzip.NewWriter(&buf)
_, err := gz.Write([]byte(data))
if err != nil {
return err
}
err = gz.Close()
if err != nil {
return err
}
// 创建请求,设置压缩相关请求头
req, err := http.NewRequest("POST", url, &buf)
if err != nil {
return err
}
req.Header.Set("Content-Encoding", "gzip")
req.Header.Set("Content-Type", "text/plain; charset=utf-8")
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// 读取响应
respData, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
fmt.Println("服务端响应:", string(respData))
return nil
}
func main() {
testData := "这是客户端发送的压缩请求数据,服务端需要先解压才能处理"
err := sendGzipRequest("http://127.0.0.1:8080/hello", testData)
if err != nil {
fmt.Println("请求失败:", err)
}
}
注意事项
- 压缩小体积数据可能不会减小体积,反而会增大,建议只对超过1KB的数据进行压缩处理
- 压缩和解压过程会消耗一定的CPU资源,需要根据业务场景权衡压缩收益和CPU开销
- HTTP压缩时需要正确设置
Content-Encoding响应头,否则客户端无法正确识别压缩格式 - gzip.NewWriter创建后必须调用Close方法,否则压缩数据可能不完整
Golanggzip压缩HTTP请求压缩gzip解压compress_gzip修改时间:2026-07-09 15:12:32