压缩算法
常用于HTTP响应压缩
- https://pkg.go.dev/compress/bzip2
- https://pkg.go.dev/compress/flate
- https://pkg.go.dev/compress/gzip
- https://pkg.go.dev/compress/lzw
- https://pkg.go.dev/compress/zlib
go
package main
import (
"bytes"
"compress/gzip"
"fmt"
"io"
"log"
)
func main() {
// 加点长度让压缩效果更明显
original := "这是一段需要被压缩的测试数据, Go 语言的压缩功能非常强大且易用" + string(make([]byte, 1000))
// 1. 压缩
var buf bytes.Buffer
writer := gzip.NewWriter(&buf)
_, err := writer.Write([]byte(original))
if err != nil {
log.Fatal("[压缩失败]", err)
}
writer.Close() // 必须关闭 writer 以写入结束标记(EOF)
compressedData := buf.Bytes() // 压缩后的数据
fmt.Printf("原始大小: %d 字节\n", len(original))
fmt.Printf("压缩后大小: %d 字节", len(compressedData))
// 2. 解压
reader, err := gzip.NewReader(bytes.NewReader(compressedData))
if err != nil {
log.Fatal("[解压失败]", err)
}
defer reader.Close() // 关闭 reader 以释放资源
decompressed, err := io.ReadAll(reader)
if err != nil {
log.Fatal("[读取失败]", err)
}
// 3.测试
if string(decompressed) == original {
fmt.Println("解压成功, 数据一致")
} else {
fmt.Println("数据不一致!")
}
}打包
常用于数据备份/或日志归档
- https://pkg.go.dev/archive/zip
- https://pkg.go.dev/archive/tar
- https://github.com/mholt/archives 推荐使用这个库, 功能更完善(多线程打包/打包进度等等)
go
package main
import (
"archive/zip"
"fmt"
"io"
"os"
"path/filepath"
)
func ZipDirs(zipOutput string, dirs []string) error {
// 创建 zip 文件
zipFile, err := os.Create(zipOutput)
if err != nil {
return fmt.Errorf("创建 zip 文件失败: %w", err)
}
defer zipFile.Close()
// 创建 zip 写入器
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
// 遍历每个目录
for _, dir := range dirs {
err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
// 跳过目录本身(只处理文件)
if d.IsDir() {
return nil
}
// 打开源文件
srcFile, err := os.Open(path)
if err != nil {
return err
}
defer srcFile.Close()
// 获取文件信息
info, err := d.Info()
if err != nil {
return err
}
// 创建 zip 文件头,保留相对路径
relPath, err := filepath.Rel(filepath.Dir(dir), path)
if err != nil {
return err
}
// 统一使用正斜杠
relPath = filepath.ToSlash(relPath)
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
header.Name = relPath
header.Method = zip.Deflate // 使用压缩
// 创建 zip 中的文件
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
// 写入文件内容
_, err = io.Copy(writer, srcFile)
return err
})
if err != nil {
return fmt.Errorf("处理目录 %s 时出错: %w", dir, err)
}
}
return nil
}
func main() {
// 要打包的目录列表
dirs := []string{
"./project/src",
"./project/config",
"./project/docs",
}
// 输出 zip 文件路径
outputZip := "./project_backup.zip"
err := ZipDirs(outputZip, dirs)
if err != nil {
fmt.Printf("打包失败: %v\n", err)
os.Exit(1)
}
fmt.Printf("成功打包为: %s\n", outputZip)
// 可选:显示压缩包内容
printZipContents(outputZip)
}
// printZipContents 打印 zip 文件中的内容列表
func printZipContents(zipPath string) {
reader, err := zip.OpenReader(zipPath)
if err != nil {
fmt.Printf("无法打开 zip 文件: %v\n", err)
return
}
defer reader.Close()
fmt.Println("\n压缩包内容:")
for _, file := range reader.File {
fmt.Printf(" %s (%d 字节)\n", file.Name, file.UncompressedSize64)
}
}