Go语言开发实现一个图片批量压缩工具

 更新时间:2025年09月11日 08:22:03   作者:程序员爱钓鱼  
在日常开发和办公中,图片体积过大会带来不少困扰,本文将使用Go语言编写一个图片批量压缩工具,文中的示例代码讲解详细,需要的可以了解下

在日常开发和办公中,图片体积过大会带来不少困扰:网页加载慢、存储占用大、邮件难以发送。很多时候,我们并不需要极致的画质,而是需要在清晰度和体积之间找到平衡。今天我们就用 Go 写一个图片批量压缩工具,从设计到实现,完整走一遍。

功能目标

  • 批量处理:支持整个目录下的所有图片文件(支持递归)。
  • 格式支持:JPEG、PNG、WebP。
  • 自定义压缩质量:用户可以通过参数指定压缩比。
  • 输出目录可选:压缩后的图片保存到指定文件夹,默认生成 output
  • 保留文件结构:输出文件夹下的路径结构与原始一致。
  • 简单易用:命令行参数运行,不依赖复杂环境。

技术选型

标准库:imageimage/jpegimage/png

第三方库:

github.com/chai2010/webp —— WebP 编解码

Go 并发:使用 goroutine + worker pool 来提升批量处理效率。

项目结构(示意)

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,           // 压缩质量(0-100)
		Workers:   4,            // 并发 worker 数
		Recursive: true,         // 是否递归
	}

	if err := run(opts); err != nil {
		fmt.Println("❌ 发生错误:", 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.查看压缩结果: 所有压缩后的图片会保存在 ./output 目录下,目录结构保持不变。

实践要点与注意事项

  • 质量参数:JPEG 和 WebP 可以用 0-100 来控制压缩比;PNG 主要通过压缩等级控制体积,但效果有限。
  • 批量优化:若图片数量很多,可以用 goroutine worker pool 提升效率,避免一次性开太多协程。
  • 格式兼容:WebP 在一些老旧系统和浏览器上兼容性不足,若是做网页资源,需要配合 fallback。
  • 压缩策略:有时候先统一缩放图片(比如长边 1080px),再压缩比单纯调整质量更省空间。

进一步扩展

  • 添加 命令行参数(例如用 flagcobra),让用户可以指定输入目录、输出目录、质量、递归开关等。
  • 支持 缩放功能(如最大宽高)。
  • 输出 统计信息(压缩前后大小对比,总共节省空间)。
  • 打包为跨平台可执行文件,方便非技术人员直接使用。

到此这篇关于Go语言开发实现一个图片批量压缩工具的文章就介绍到这了,更多相关Go图片批量压缩内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • GO中的条件变量sync.Cond详解

    GO中的条件变量sync.Cond详解

    条件变量是基于互斥锁的,它必须基于互斥锁才能发挥作用,条件变量的初始化离不开互斥锁,并且它的方法有点也是基于互斥锁的,这篇文章主要介绍了GO的条件变量sync.Cond,需要的朋友可以参考下
    2023-01-01
  • 详解Golang中日志库glog的使用

    详解Golang中日志库glog的使用

    golang/glog 是 C++ 版本 google/glog 的 Go 版本实现,基本实现了原生 glog 的日志格式,下面大家就跟随小编一起了解一下glog的具体使用吧
    2023-09-09
  • Go 语言 net/http 包使用之HTTP 服务器、客户端与中间件详解

    Go 语言 net/http 包使用之HTTP 服务器、客户端与中间件详解

    Go 语言标准库中的net/http包十分的优秀,提供了非常完善的 HTTP 客户端与服务端的实现,仅通过几行代码就可以搭建一个非常简单的 HTTP 服务器,本文给大家介绍Go语言net/http包使用之HTTP服务器、客户端与中间件的操作,感兴趣的朋友一起看看吧
    2025-05-05
  • goland中使用leetcode插件实现

    goland中使用leetcode插件实现

    本文主要介绍了goland中使用leetcode插件实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • Go语言中的定时器原理与实战应用

    Go语言中的定时器原理与实战应用

    在Go语言中,Timer和Ticker是处理定时任务的重要工具,Timer用于一次性事件,而Ticker则用于周期性事件,本文详细介绍了这两种定时器的创建、使用和停止方法,并通过实际案例展示了它们在监控日志、检查系统状态等方面的应用
    2024-10-10
  • Golang 单元测试和基准测试实例详解

    Golang 单元测试和基准测试实例详解

    这篇文章主要为大家介绍了Golang 单元测试和基准测试实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Golang关键字defer的用法详解

    Golang关键字defer的用法详解

    defer是Go里面的一个关键字,用在方法或函数前面,作为方法或函数的延迟调用。这篇文章主要为大家介绍了defer的简单使用,需要的可以参考一下
    2023-05-05
  • Go gRPC环境安装教程示例详解

    Go gRPC环境安装教程示例详解

    这篇文章主要为大家介绍了Go gRPC环境安装的教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 详解如何使用Go的Viper来解析配置信息

    详解如何使用Go的Viper来解析配置信息

    Viper库为Golang语言开发者提供了对不同数据源和不同格式的配置文件的读取,是Go项目读取配置的神器,我们今天就来讲讲如何使用Viper来解析配置信息,文中通过代码示例讲解非常详细,需要的朋友可以参考下
    2024-01-01
  • golang拼接字符串的5种实现方式

    golang拼接字符串的5种实现方式

    文章总结了五种拼接字符串的方式,包括使用 "+"、strings.Join()、fmt.Sprint、bytes.Buffer 和 strings.Builder,每种方式都有其适用场景和性能特点
    2024-12-12

最新评论