Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Go 语言标准库 —— compress/zlib 包(Zlib 压缩/解压缩)


🔹 概述

compress/zlib 包实现了 RFC 1950 定义的 Zlib 压缩格式。

主要功能:

  • Zlib 格式压缩
  • Zlib 格式解压缩
  • 支持自定义压缩级别
  • 支持 Adler-32 校验和
  • 流式处理

重要说明:

  • Zlib 基于 DEFLATE 算法(compress/flate)
  • 添加了文件头和 Adler-32 校验
  • 支持 .zlib 文件扩展名
  • 广泛应用于网络传输、PNG 图像、Git 版本控制

压缩级别:

  • NoCompression (0) - 不压缩
  • BestSpeed (1) - 最快压缩
  • BestCompression (9) - 最大压缩
  • DefaultCompression (-1) - 默认压缩
  • HuffmanOnly (-2) - 仅 Huffman 编码
  • ConstantCompression (-2) - 常量压缩

与 Gzip 的区别:

  • Zlib:RFC 1950,使用 Adler-32 校验,适合网络传输
  • Gzip:RFC 1952,使用 CRC32 校验,适合文件压缩

🔹 核心类型

Zlib 写入器(压缩)

zlib.Writer struct

  • 说明:

    • 实现了 io.WriteCloser 接口
    • 将写入的数据进行 Zlib 压缩
    • 自动添加文件头、Adler-32 校验
    • 支持自定义压缩级别
  • 字段:

    • 内部自动管理,无需手动操作
  • 创建方式:

    // 创建新的写入器(默认压缩级别)
    func NewWriter(w io.Writer) *Writer
    
    // 创建新的写入器(指定压缩级别)
    func NewWriterLevel(w io.Writer, level int) (*Writer, error)
    
  • 常用方法详解

    • Write 方法

      • 说明:写入并压缩数据
      • 方法:Write(p []byte) (n int, err error)
      • 注意:
        • 数据会被缓冲并压缩
        • 返回写入的字节数(压缩前)
      • 示例:
        writer, _ := zlib.NewWriterLevel(file, zlib.DefaultCompression)
        defer writer.Close()
        
        writer.Write([]byte("hello world"))
        
    • Flush 方法

      • 说明:刷新缓冲区,强制输出所有 pending 数据
      • 方法:Flush() error
      • 注意:
        • 不会关闭写入器
        • 适合流式传输场景
      • 示例:
        writer.Write(data)
        writer.Flush() // 强制输出
        
    • Close 方法

      • 说明:关闭写入器,写入文件尾和 Adler-32 校验和
      • 方法:Close() error
      • 注意:
        • 必须先调用 Close 才能完成压缩
        • 之后不能再写入
      • 示例:
        writer.Write(data)
        err := writer.Close() // 完成压缩
        
    • Reset 方法

      • 说明:重置写入器,复用对象
      • 方法:Reset(w io.Writer)
      • 注意:
        • 保持压缩级别不变
        • 减少内存分配
      • 示例:
        writer.Reset(newFile) // 复用写入器
        
  • 示例(完整)

    package main
    
    import (
    	"bytes"
    	"compress/zlib"
    	"fmt"
    	"io"
    	"os"
    )
    
    func main() {
    	// 原始数据
    	data := []byte("Hello, World! This is a test of Zlib compression.")
    
    	// 创建缓冲区存储压缩数据
    	var compressed bytes.Buffer
    
    	// 创建 zlib 写入器(默认压缩级别)
    	writer := zlib.NewWriter(&compressed)
    
    	// 写入数据
    	_, err := writer.Write(data)
    	if err != nil {
    		fmt.Println("写入失败:", err)
    		return
    	}
    
    	// 关闭写入器(必须)
    	err = writer.Close()
    	if err != nil {
    		fmt.Println("关闭失败:", err)
    		return
    	}
    
    	// 显示压缩效果
    	fmt.Printf("原始大小:%d 字节\n", len(data))
    	fmt.Printf("压缩大小:%d 字节\n", compressed.Len())
    	fmt.Printf("压缩率:%.2f%%\n", float64(compressed.Len())/float64(len(data))*100)
    }
    

Zlib 读取器(解压缩)

zlib.Reader struct

  • 说明:

    • 实现了 io.ReadCloser 接口
    • 从底层读取器读取压缩数据并解压缩
    • 自动处理文件头、Adler-32 校验
    • 流式处理,不需要一次性加载全部数据
  • 字段:

    • 内部自动管理,无需手动操作
  • 创建方式:

    // 创建新的读取器
    func NewReader(r io.Reader) (io.ReadCloser, error)
    
  • 常用方法详解

    • Read 方法

      • 说明:读取并解压缩数据
      • 方法:Read(p []byte) (n int, err error)
      • 注意:
        • 实现了 io.Reader 接口
        • 自动处理解压缩和 Adler-32 校验
        • 读到末尾返回 io.EOF
      • 示例:
        reader, _ := zlib.NewReader(file)
        defer reader.Close()
        
        data, err := io.ReadAll(reader)
        
    • Close 方法

      • 说明:关闭读取器,释放资源
      • 方法:Close() error
      • 注意:
        • 使用完后必须关闭
        • 之后不能再读取
      • 示例:
        reader := zlib.NewReader(file)
        defer reader.Close()
        
  • 示例(完整)

    package main
    
    import (
    	"bytes"
    	"compress/zlib"
    	"fmt"
    	"io"
    )
    
    func main() {
    	// 假设已有压缩数据
    	compressedData := []byte{ /* ... zlib 压缩数据 ... */ }
    
    	// 创建 zlib 读取器
    	reader, err := zlib.NewReader(bytes.NewReader(compressedData))
    	if err != nil {
    		fmt.Println("创建读取器失败:", err)
    		return
    	}
    	defer reader.Close()
    
    	// 读取并解压缩
    	data, err := io.ReadAll(reader)
    	if err != nil {
    		fmt.Println("解压失败:", err)
    		return
    	}
    
    	fmt.Printf("解压后大小:%d 字节\n", len(data))
    	fmt.Printf("内容:%s\n", string(data))
    }
    

🔹 使用场景

1. 基础压缩和解压缩

package main

import (
	"bytes"
	"compress/zlib"
	"fmt"
	"io"
)

func main() {
	// 原始数据
	original := []byte("Hello, World! This is a test of Zlib compression algorithm.")

	// 压缩
	var compressed bytes.Buffer
	writer := zlib.NewWriter(&compressed)
	writer.Write(original)
	writer.Close()

	// 解压缩
	reader, err := zlib.NewReader(&compressed)
	if err != nil {
		fmt.Println("创建读取器失败:", err)
		return
	}
	defer reader.Close()

	decompressed, err := io.ReadAll(reader)
	if err != nil {
		fmt.Println("解压失败:", err)
		return
	}

	// 验证
	fmt.Printf("原始大小:%d 字节\n", len(original))
	fmt.Printf("压缩大小:%d 字节\n", compressed.Len())
	fmt.Printf("解压大小:%d 字节\n", len(decompressed))
	fmt.Printf("数据一致:%v\n", bytes.Equal(original, decompressed))
}

2. 文件压缩和解压缩

package main

import (
	"compress/zlib"
	"fmt"
	"io"
	"os"
)

func compressFile(src, dst string, level int) error {
	// 打开源文件
	srcFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("打开源文件:%w", err)
	}
	defer srcFile.Close()

	// 创建目标文件
	dstFile, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("创建目标文件:%w", err)
	}
	defer dstFile.Close()

	// 创建 zlib 写入器
	var writer *zlib.Writer
	if level == zlib.DefaultCompression {
		writer = zlib.NewWriter(dstFile)
	} else {
		writer, err = zlib.NewWriterLevel(dstFile, level)
		if err != nil {
			return fmt.Errorf("创建压缩器:%w", err)
		}
	}
	defer writer.Close()

	// 复制并压缩
	_, err = io.Copy(writer, srcFile)
	if err != nil {
		return fmt.Errorf("压缩失败:%w", err)
	}

	// 显示压缩效果
	srcInfo, _ := os.Stat(src)
	dstInfo, _ := os.Stat(dst)
	ratio := float64(dstInfo.Size()) / float64(srcInfo.Size()) * 100

	fmt.Printf("压缩完成:%s -> %s\n", src, dst)
	fmt.Printf("压缩率:%.2f%%\n", ratio)

	return nil
}

func decompressFile(src, dst string) error {
	// 打开源文件
	srcFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("打开源文件:%w", err)
	}
	defer srcFile.Close()

	// 创建目标文件
	dstFile, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("创建目标文件:%w", err)
	}
	defer dstFile.Close()

	// 创建 zlib 读取器
	reader, err := zlib.NewReader(srcFile)
	if err != nil {
		return fmt.Errorf("创建解压读取器:%w", err)
	}
	defer reader.Close()

	_, err = io.Copy(dstFile, reader)
	if err != nil {
		return fmt.Errorf("解压失败:%w", err)
	}

	fmt.Println("解压成功")
	return nil
}

func main() {
	// 示例:安全压缩
	err := safeCompress("input.txt", "output.zlib")
	if err != nil {
		fmt.Println("压缩错误:", err)
	}

	// 示例:安全解压
	err = safeDecompress("output.zlib", "restored.txt")
	if err != nil {
		fmt.Println("解压错误:", err)
	}
}

🔹 性能优化

1. 对象池复用

package main

import (
	"bytes"
	"compress/zlib"
	"sync"
)

var writerPool = sync.Pool{
	New: func() interface{} {
		w, _ := zlib.NewWriterLevel(nil, zlib.DefaultCompression)
		return w
	},
}

func compress(data []byte) ([]byte, error) {
	writer := writerPool.Get().(*zlib.Writer)
	defer writerPool.Put(writer)

	var buf bytes.Buffer
	writer.Reset(&buf)
	
	_, err := writer.Write(data)
	if err != nil {
		writer.Close()
		return nil, err
	}
	
	err = writer.Close()
	if err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}

2. 流式处理大文件

package main

import (
	"compress/zlib"
	"fmt"
	"io"
	"os"
)

func streamCompress(src, dst string) error {
	srcFile, err := os.Open(src)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	dstFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer dstFile.Close()

	writer := zlib.NewWriter(dstFile)
	defer writer.Close()

	buf := make([]byte, 32*1024) // 32KB 缓冲
	total := 0

	for {
		n, err := srcFile.Read(buf)
		if n > 0 {
			_, werr := writer.Write(buf[:n])
			if werr != nil {
				return werr
			}
			total += n
		}

		if err == io.EOF {
			break
		}
		if err != nil {
			return err
		}
	}

	fmt.Printf("流式压缩完成:%d 字节\n", total)
	return nil
}

🔹 Zlib vs Gzip vs DEFLATE 对比

格式对比

特性DEFLATEZlibGzip
标准RFC 1951RFC 1950RFC 1952
头部2 字节10+ 字节
校验Adler-32CRC32
尾部4 字节8 字节
压缩算法DEFLATEDEFLATEDEFLATE
Go 包compress/flatecompress/zlibcompress/gzip

选择指南

使用 DEFLATE (compress/flate):

  • ✅ 需要自定义协议
  • ✅ 底层压缩需求
  • ✅ 嵌入到其他格式中

使用 Zlib (compress/zlib):

  • ✅ 网络数据传输
  • ✅ PNG 图像格式
  • ✅ Git 对象存储
  • ✅ 内存数据压缩
  • ✅ 需要快速压缩/解压

使用 Gzip (compress/gzip):

  • ✅ 文件压缩
  • ✅ HTTP 响应压缩
  • ✅ 日志文件压缩
  • ✅ 归档备份
  • ✅ 需要高压缩率

🔥 总结

核心类型

  • zlib.Writer - 压缩写入器(io.WriteCloser)
  • zlib.Reader - 解压缩读取器(io.ReadCloser)

核心函数

  • zlib.NewWriter(w io.Writer) - 创建压缩器(默认级别)
  • zlib.NewWriterLevel(w io.Writer, level int) - 创建压缩器(指定级别)
  • zlib.NewReader(r io.Reader) - 创建解压器

压缩级别

级别说明场景
NoCompression0不压缩已压缩数据
BestSpeed1最快实时传输
DefaultCompression-1默认一般用途
BestCompression9最大压缩归档存储

主要特点

  • 标准格式 👉 RFC 1950 Zlib 标准
  • Adler-32 校验 👉 快速校验和算法
  • 可调节级别 👉 从 0 到 9 多个压缩级别
  • 流式处理 👉 支持实时数据流
  • 广泛应用 👉 PNG、Git、网络传输

使用场景

  • 网络传输 👉 HTTP、WebSocket 数据压缩
  • PNG 图像 👉 图像数据压缩
  • Git 版本 👉 对象存储压缩
  • 内存数据 👉 临时数据压缩
  • 实时流式 👉 流式压缩/解压

与其他包配合

  • image/png 👉 PNG 图像处理
  • net/http 👉 HTTP 数据传输
  • bufio 👉 提高 I/O 性能
  • io 👉 Copy、ReadAll 等操作

最佳实践

  • ✅ 始终调用 Close() 完成压缩
  • ✅ 使用 defer 确保资源释放
  • ✅ 选择合适的压缩级别
  • ✅ 使用对象池提高性能
  • ✅ 完善的错误处理
  • ✅ 流式处理大文件
  • ⚠️ 注意:必须调用 Close() 才能写入校验和

性能提示

  • 速度优先 👉 BestSpeed 或 NoCompression
  • 空间优先 👉 BestCompression
  • 平衡 👉 DefaultCompression(推荐)
  • 大文件 👉 使用流式处理和缓冲
  • 多次压缩 👉 使用对象池复用

**compress/zlib 包提供了广泛使用的 Zlib 压缩功能,适合网络传输、PNG 图像、Git 存储等各种场景!**读取器:%w“, err) } defer reader.Close()

_, err = io.Copy(dstFile, reader)
if err != nil {
	return fmt.Errorf("解压失败:%w", err)
}

err = reader.Close()
if err != nil {
	return fmt.Errorf("关闭解压器:%w", err)
}

fmt.Println("解压成功")
return nil

}

func main() { // 示例:安全压缩 err := safeCompress(“input.txt”, “output.zlib”) if err != nil { fmt.Println(“压缩错误:”, err) }

// 示例:安全解压
err = safeDecompress("output.zlib", "restored.txt")
if err != nil {
	fmt.Println("解压错误:", err)
}

}


---

## 🔹 总结

### 核心要点

| 特性 | 说明 |
|------|------|
| **压缩格式** | RFC 1950 Zlib 格式 |
| **校验算法** | Adler-32 校验和 |
| **压缩算法** | 基于 DEFLATE (compress/flate) |
| **接口实现** | io.WriteCloser (压缩), io.ReadCloser (解压) |
| **压缩级别** | 0-9 及特殊值 (-1, -2) |

### 最佳实践

1. **始终调用 Close()**
   - 压缩:必须调用 `Close()` 完成压缩并写入校验和
   - 解压:必须调用 `Close()` 释放资源
   - 推荐使用 `defer` 确保关闭

2. **错误处理**
   - 检查 `NewWriter`/`NewReader` 返回的错误
   - 检查 `Write`/`Read` 操作错误
   - 检查 `Close` 操作错误

3. **性能优化**
   - 使用 `Reset()` 复用写入器对象
   - 根据场景选择合适的压缩级别
   - 流式处理大文件,避免内存溢出

4. **使用场景**
   - ✅ 网络数据传输(HTTP、WebSocket)
   - ✅ PNG 图像压缩
   - ✅ Git 对象存储
   - ✅ 实时流式压缩
   - ❌ 大文件归档(建议使用 Gzip)

### 与 Gzip 对比

| 特性 | Zlib | Gzip |
|------|------|------|
| RFC 标准 | RFC 1950 | RFC 1952 |
| 校验和 | Adler-32 | CRC32 |
| 文件头 | 2 字节 | 10+ 字节 |
| 适用场景 | 网络传输、内存数据 | 文件压缩、归档 |
| 压缩率 | 略低 | 略高 |
| 速度 | 略快 | 略慢 |

### 完整示例索引

1. ✅ 基础压缩和解压缩
2. ✅ 文件压缩和解压缩
3. ✅ HTTP 数据传输压缩
4. ✅ PNG 图像处理
5. ✅ Git 对象存储
6. ✅ 压缩级别对比
7. ✅ 错误处理最佳实践

---

**📚 相关文档:**
- [Go compress/zlib 官方文档](https://pkg.go.dev/compress/zlib)
- [RFC 1950 - ZLIB Compressed Data Format](https://tools.ietf.org/html/rfc1950)
- [RFC 1951 - DEFLATE Compressed Data Format](https://tools.ietf.org/html/rfc1951)

**💡 提示:** 对于文件压缩场景,优先考虑 `compress/gzip` 包;对于网络传输和内存数据压缩,`compress/zlib` 是更好的选择。读取器:%w", err)
	}
	defer reader.Close()

	// 复制并解压缩
	_, err = io.Copy(dstFile, reader)
	if err != nil {
		return fmt.Errorf("解压失败:%w", err)
	}

	// 显示解压效果
	srcInfo, _ := os.Stat(src)
	dstInfo, _ := os.Stat(dst)
	ratio := float64(dstInfo.Size()) / float64(srcInfo.Size()) * 100

	fmt.Printf("解压完成:%s -> %s\n", src, dst)
	fmt.Printf("解压后大小:%.2f%%\n", ratio)

	return nil
}

func main() {
	// 示例:压缩文件
	err := compressFile("input.txt", "output.zlib", zlib.DefaultCompression)
	if err != nil {
		fmt.Println("压缩失败:", err)
		return
	}

	// 示例:解压文件
	err = decompressFile("output.zlib", "restored.txt")
	if err != nil {
		fmt.Println("解压失败:", err)
		return
	}

	fmt.Println("\n文件压缩/解压缩完成!")
}

3. HTTP 数据传输压缩

package main

import (
	"bytes"
	"compress/zlib"
	"fmt"
	"io"
	"net/http"
)

// 压缩数据并通过 HTTP 发送
func sendCompressedData(url string, data []byte) error {
	// 压缩数据
	var compressed bytes.Buffer
	writer := zlib.NewWriter(&compressed)
	_, err := writer.Write(data)
	if err != nil {
		writer.Close()
		return err
	}
	writer.Close()

	// 发送 HTTP 请求
	resp, err := http.Post(url, "application/zlib", &compressed)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("HTTP 错误:%s", resp.Status)
	}

	fmt.Println("数据发送成功")
	return nil
}

// 接收并解压 HTTP 数据
func receiveAndDecompress(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 创建 zlib 读取器
	reader, err := zlib.NewReader(resp.Body)
	if err != nil {
		return nil, err
	}
	defer reader.Close()

	// 读取解压后的数据
	return io.ReadAll(reader)
}

func main() {
	// 示例:发送压缩数据
	data := []byte("Important data to send")
	err := sendCompressedData("http://example.com/upload", data)
	if err != nil {
		fmt.Println("发送失败:", err)
	}

	// 示例:接收压缩数据
	// received, err := receiveAndDecompress("http://example.com/data")
}

4. PNG 图像处理(Zlib 压缩)

package main

import (
	"bytes"
	"compress/zlib"
	"fmt"
	"image"
	"image/png"
	"io"
	"os"
)

// 压缩 PNG 图像数据
func compressImageData(data []byte) ([]byte, error) {
	var buf bytes.Buffer
	writer := zlib.NewWriter(&buf)
	
	_, err := writer.Write(data)
	if err != nil {
		writer.Close()
		return nil, err
	}
	
	err = writer.Close()
	if err != nil {
		return nil, err
	}
	
	return buf.Bytes(), nil
}

// 解压缩 PNG 图像数据
func decompressImageData(data []byte) ([]byte, error) {
	reader, err := zlib.NewReader(bytes.NewReader(data))
	if err != nil {
		return nil, err
	}
	defer reader.Close()
	
	return io.ReadAll(reader)
}

// 读取 PNG 文件并压缩其数据
func processPNG(filename string) error {
	// 打开 PNG 文件
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	// 解码 PNG
	img, err := png.Decode(file)
	if err != nil {
		return err
	}

	// 获取图像边界
	bounds := img.Bounds()
	
	// 提取像素数据
	var pixelData bytes.Buffer
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			r, g, b, a := img.At(x, y).RGBA()
			pixelData.WriteByte(byte(r >> 8))
			pixelData.WriteByte(byte(g >> 8))
			pixelData.WriteByte(byte(b >> 8))
			pixelData.WriteByte(byte(a >> 8))
		}
	}

	// 压缩像素数据
	compressed, err := compressImageData(pixelData.Bytes())
	if err != nil {
		return err
	}

	fmt.Printf("原始像素数据:%d 字节\n", pixelData.Len())
	fmt.Printf("压缩后:%d 字节\n", len(compressed))
	fmt.Printf("压缩率:%.2f%%\n", float64(len(compressed))/float64(pixelData.Len())*100)

	return nil
}

func main() {
	// 处理 PNG 文件
	err := processPNG("image.png")
	if err != nil {
		fmt.Println("处理失败:", err)
		return
	}
	fmt.Println("处理完成")
}

5. Git 对象存储(Zlib 压缩)

package main

import (
	"bytes"
	"compress/zlib"
	"crypto/sha1"
	"fmt"
	"io"
	"os"
	"path/filepath"
)

// Git 对象类型
type GitObjectType string

const (
	GitBlob   GitObjectType = "blob"
	GitTree   GitObjectType = "tree"
	GitCommit GitObjectType = "commit"
)

// 创建 Git 对象(压缩并存储)
func createGitObject(objType GitObjectType, data []byte) (string, error) {
	// 构建 Git 对象内容:type + " " + size + "\0" + content
	header := fmt.Sprintf("%s %d", objType, len(data))
	content := append([]byte(header), 0)
	content = append(content, data...)

	// 计算 SHA1 哈希
	hash := sha1.Sum(content)
	hashStr := fmt.Sprintf("%x", hash)

	// 压缩内容
	var compressed bytes.Buffer
	writer := zlib.NewWriter(&compressed)
	_, err := writer.Write(content)
	if err != nil {
		writer.Close()
		return "", err
	}
	writer.Close()

	// 存储到 .git/objects 目录
	objectDir := filepath.Join(".git", "objects", hashStr[:2])
	os.MkdirAll(objectDir, 0755)

	objectPath := filepath.Join(objectDir, hashStr[2:])
	err = os.WriteFile(objectPath, compressed.Bytes(), 0644)
	if err != nil {
		return "", err
	}

	return hashStr, nil
}

// 读取 Git 对象(解压并读取)
func readGitObject(hash string) ([]byte, error) {
	objectPath := filepath.Join(".git", "objects", hash[:2], hash[2:])
	
	data, err := os.ReadFile(objectPath)
	if err != nil {
		return nil, err
	}

	// 解压
	reader, err := zlib.NewReader(bytes.NewReader(data))
	if err != nil {
		return nil, err
	}
	defer reader.Close()

	return io.ReadAll(reader)
}

func main() {
	// 创建 Git blob 对象
	content := []byte("Hello, Git!")
	hash, err := createGitObject(GitBlob, content)
	if err != nil {
		fmt.Println("创建对象失败:", err)
		return
	}

	fmt.Printf("创建对象:%s\n", hash)

	// 读取 Git 对象
	data, err := readGitObject(hash)
	if err != nil {
		fmt.Println("读取对象失败:", err)
		return
	}

	// 解析内容(跳过头部)
	nullIndex := bytes.IndexByte(data, 0)
	if nullIndex >= 0 {
		fmt.Printf("对象内容:%s\n", string(data[nullIndex+1:]))
	}
}

6. 压缩级别对比

package main

import (
	"bytes"
	"compress/zlib"
	"fmt"
	"math/rand"
	"time"
)

func benchmark(data []byte, level int) (compressedSize int, duration time.Duration) {
	var buf bytes.Buffer
	writer, _ := zlib.NewWriterLevel(&buf, level)

	start := time.Now()
	writer.Write(data)
	writer.Close()
	duration = time.Since(start)

	return buf.Len(), duration
}

func main() {
	// 生成随机数据(可压缩的文本)
	rand.Seed(time.Now().UnixNano())
	data := []byte("Hello, World! This is a test of Zlib compression. " +
		"Zlib is widely used in many applications. " +
		"It provides good compression ratio and fast speed. " +
		"Repeat this text many times to make it more compressible. ")
	
	// 重复多次以增加数据量
	for i := 0; i < 100; i++ {
		data = append(data, data...)
	}

	levels := []struct {
		name  string
		level int
	}{
		{"NoCompression", zlib.NoCompression},
		{"BestSpeed", zlib.BestSpeed},
		{"DefaultCompression", zlib.DefaultCompression},
		{"BestCompression", zlib.BestCompression},
	}

	fmt.Printf("原始大小:%d 字节\n\n", len(data))
	fmt.Println("压缩级别对比:")
	fmt.Println("----------------------------------------")

	for _, l := range levels {
		size, duration := benchmark(data, l.level)
		ratio := float64(size) / float64(len(data)) * 100
		fmt.Printf("%-20s: %6d 字节 (%5.2f%%), 耗时 %v\n",
			l.name, size, ratio, duration)
	}
}

🔹 错误处理

常见错误

  • 无效的 zlib 格式

    • 说明:尝试解压非 zlib 格式的数据
    • 处理方式:检查错误并验证数据格式
    • 示例:
      reader, err := zlib.NewReader(file)
      if err != nil {
      	fmt.Println("无效的 zlib 格式:", err)
      }
      
  • Adler-32 校验失败

    • 说明:压缩数据损坏
    • 处理方式:读取时检查错误
    • 示例:
      data, err := io.ReadAll(reader)
      if err != nil {
      	fmt.Println("校验失败:", err)
      }
      
  • 写入器未关闭

    • 说明:忘记调用 Close() 导致数据不完整
    • 处理方式:始终使用 defer Close()
    • 示例:
      writer := zlib.NewWriter(dst)
      defer writer.Close() // 确保关闭
      

错误处理最佳实践

package main

import (
	"compress/zlib"
	"fmt"
	"io"
	"os"
)

func safeCompress(src, dst string) (err error) {
	srcFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("打开源文件:%w", err)
	}
	defer srcFile.Close()

	dstFile, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("创建目标文件:%w", err)
	}
	defer func() {
		dstFile.Close()
		if err != nil {
			os.Remove(dst)
		}
	}()

	writer := zlib.NewWriter(dstFile)
	defer writer.Close()

	_, err = io.Copy(writer, srcFile)
	if err != nil {
		return fmt.Errorf("压缩失败:%w", err)
	}

	err = writer.Close()
	if err != nil {
		return fmt.Errorf("关闭压缩器:%w", err)
	}

	fmt.Println("压缩成功")
	return nil
}

func safeDecompress(src, dst string) (err error) {
	srcFile, err := os.Open(src)
	if err != nil {
		return fmt.Errorf("打开源文件:%w", err)
	}
	defer srcFile.Close()

	dstFile, err := os.Create(dst)
	if err != nil {
		return fmt.Errorf("创建目标文件:%w", err)
	}
	defer func() {
		dstFile.Close()
		if err != nil {
			os.Remove(dst)
		}
	}()

	reader, err := zlib.NewReader(srcFile)
	if err != nil {
		return fmt.Errorf("创建解压