Go語言開發(fā)實現(xiàn)一個圖片批量壓縮工具
在日常開發(fā)和辦公中,圖片體積過大會帶來不少困擾:網(wǎng)頁加載慢、存儲占用大、郵件難以發(fā)送。很多時候,我們并不需要極致的畫質(zhì),而是需要在清晰度和體積之間找到平衡。今天我們就用 Go 寫一個圖片批量壓縮工具,從設(shè)計到實現(xiàn),完整走一遍。
功能目標(biāo)
- 批量處理:支持整個目錄下的所有圖片文件(支持遞歸)。
- 格式支持:JPEG、PNG、WebP。
- 自定義壓縮質(zhì)量:用戶可以通過參數(shù)指定壓縮比。
- 輸出目錄可選:壓縮后的圖片保存到指定文件夾,默認生成
output。 - 保留文件結(jié)構(gòu):輸出文件夾下的路徑結(jié)構(gòu)與原始一致。
- 簡單易用:命令行參數(shù)運行,不依賴復(fù)雜環(huán)境。
技術(shù)選型
標(biāo)準庫:image、image/jpeg、image/png
第三方庫:
github.com/chai2010/webp —— WebP 編解碼
Go 并發(fā):使用 goroutine + worker pool 來提升批量處理效率。
項目結(jié)構(gòu)(示意)
img-compressor/
├── main.go
├── go.mod
完整代碼(main.go)
package main
import (
"fmt"
"image"
"image/jpeg"
"image/png"
"os"
"path/filepath"
"strings"
"sync"
"github.com/chai2010/webp"
)
type Options struct {
InputDir string
OutputDir string
Quality int
Workers int
Recursive bool
}
func main() {
opts := Options{
InputDir: "./images", // 輸入目錄
OutputDir: "./output", // 輸出目錄
Quality: 75, // 壓縮質(zhì)量(0-100)
Workers: 4, // 并發(fā) worker 數(shù)
Recursive: true, // 是否遞歸
}
if err := run(opts); err != nil {
fmt.Println("? 發(fā)生錯誤:", err)
os.Exit(1)
}
fmt.Println("? 批量壓縮完成!")
}
func run(opts Options) error {
// 收集所有待處理文件
var files []string
err := filepath.Walk(opts.InputDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
if path != opts.InputDir && !opts.Recursive {
return filepath.SkipDir
}
return nil
}
ext := strings.ToLower(filepath.Ext(info.Name()))
if ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".webp" {
files = append(files, path)
}
return nil
})
if err != nil {
return err
}
if len(files) == 0 {
return fmt.Errorf("沒有找到任何圖片文件")
}
// worker pool
fileCh := make(chan string)
var wg sync.WaitGroup
for i := 0; i < opts.Workers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for f := range fileCh {
if err := compressImage(f, opts); err != nil {
fmt.Printf("?? 壓縮失敗 %s: %v\n", f, err)
} else {
fmt.Printf("? 壓縮完成: %s\n", f)
}
}
}()
}
for _, f := range files {
fileCh <- f
}
close(fileCh)
wg.Wait()
return nil
}
// 壓縮單張圖片
func compressImage(path string, opts Options) error {
inFile, err := os.Open(path)
if err != nil {
return err
}
defer inFile.Close()
img, format, err := image.Decode(inFile)
if err != nil {
return fmt.Errorf("解碼失敗: %w", err)
}
// 輸出路徑
rel, _ := filepath.Rel(opts.InputDir, path)
outPath := filepath.Join(opts.OutputDir, rel)
if err := os.MkdirAll(filepath.Dir(outPath), 0755); err != nil {
return err
}
outFile, err := os.Create(outPath)
if err != nil {
return err
}
defer outFile.Close()
switch format {
case "jpeg":
err = jpeg.Encode(outFile, img, &jpeg.Options{Quality: opts.Quality})
case "png":
encoder := png.Encoder{CompressionLevel: png.BestCompression}
err = encoder.Encode(outFile, img)
case "webp":
err = webp.Encode(outFile, img, &webp.Options{Quality: float32(opts.Quality)})
default:
return fmt.Errorf("不支持的格式: %s", format)
}
return err
}
使用方法
1.初始化項目并安裝依賴:
go mod init img-compressor go get github.com/chai2010/webp
2.放置圖片到 ./images 目錄。
3.運行程序:
go run main.go
4.查看壓縮結(jié)果: 所有壓縮后的圖片會保存在 ./output 目錄下,目錄結(jié)構(gòu)保持不變。
實踐要點與注意事項
- 質(zhì)量參數(shù):JPEG 和 WebP 可以用
0-100來控制壓縮比;PNG 主要通過壓縮等級控制體積,但效果有限。 - 批量優(yōu)化:若圖片數(shù)量很多,可以用 goroutine worker pool 提升效率,避免一次性開太多協(xié)程。
- 格式兼容:WebP 在一些老舊系統(tǒng)和瀏覽器上兼容性不足,若是做網(wǎng)頁資源,需要配合 fallback。
- 壓縮策略:有時候先統(tǒng)一縮放圖片(比如長邊 1080px),再壓縮比單純調(diào)整質(zhì)量更省空間。
進一步擴展
- 添加 命令行參數(shù)(例如用
flag或cobra),讓用戶可以指定輸入目錄、輸出目錄、質(zhì)量、遞歸開關(guān)等。 - 支持 縮放功能(如最大寬高)。
- 輸出 統(tǒng)計信息(壓縮前后大小對比,總共節(jié)省空間)。
- 打包為跨平臺可執(zhí)行文件,方便非技術(shù)人員直接使用。
到此這篇關(guān)于Go語言開發(fā)實現(xiàn)一個圖片批量壓縮工具的文章就介紹到這了,更多相關(guān)Go圖片批量壓縮內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go?語言?net/http?包使用之HTTP?服務(wù)器、客戶端與中間件詳解
Go 語言標(biāo)準庫中的net/http包十分的優(yōu)秀,提供了非常完善的 HTTP 客戶端與服務(wù)端的實現(xiàn),僅通過幾行代碼就可以搭建一個非常簡單的 HTTP 服務(wù)器,本文給大家介紹Go語言net/http包使用之HTTP服務(wù)器、客戶端與中間件的操作,感興趣的朋友一起看看吧2025-05-05

