Go批量处理图片需用os.ReadDir遍历目录、校验.jpg/.jpeg后缀、image.Decode自动解码;缩放用golang.org/x/image/draw.ApproxBiLinear;WebP编码需webp.Options{Lossless:false,Quality:75};并发用带缓冲channel限流。
image/jpeg 和 os.ReadDir 批量读取并解码图片Go 标准库不支持直接批量加载,必须手动遍历目录、逐个打开并解码。常见错误是忽略文件扩展名校验,导致 jpeg.Decode 或 png.Decode 在非图像文件上 panic。
os.ReadDir(Go 1.16+)列出目录项,避免 filepath.Walk 的递归干扰entry.Name() 做后缀判断:strings.HasSuffix(strings.ToLower(name), ".jpg"),注意大小写image.Decode(自动识别格式)比硬写 jpeg.Decode 更稳妥;但若只处理 JPEG,显式调用可提前暴露格式错误err:解码失败时返回的不是 nil 图像,而是 nil, err,直接 deref 会 panicgolang.org/x/image/draw 而非手动重采样标准库 image 包不提供缩放函数,自己实现双线性插值容易出边界或性能问题。社区方案中 draw.ApproxBiLinear 是最轻量且足够清晰的选择。
dst := image.NewRGBA(image.Rect(0, 0, width, height))
draw.ApproxBiLinear.Scale,注意第 4 个参数是源图像的 image.Rectangle,别传 src.Bounds() 以外的范围dst 图像对象(重设尺寸后 dst.Bounds().Max.X/Y),减少 GC 压力draw.CatmullRom:质量高但慢 3–5 倍,批量场景下得不偿失golang.org/x/image/webp 并注意编码参数标准库不支持 WebP,必须额外依赖。常见坑是忽略 webp.Options 中的 Lossless 和 Quality 冲突——设了 Quality=80 却开 Lo,会导致静默降级为无损模式,体积反而更大。
go get golang.org/x/image/webp
*image.RGBA 或 *image.YCbCr,*image.NRGBA 需转换webp.Options{Lossless: false, Quality: 75},平衡体积与细节os.Create 后直接传给 webp.Encode,不要中间套 bytes.Buffer——内存放大明显直接对每个文件起 goroutine(如 go process(file))在千张图场景下会瞬间拉起上千 goroutine,调度开销大,还可能触发系统 open files 限制。
sem := make(chan struct{}, 4) 控制并发数(4 是常见安全值,可根据 CPU 核心数微调)sem ,结束后
sync.WaitGroup + sync.Mutex 管理错误切片,别只打印不聚合os.Open 和 jpeg.Decode 都可能阻塞,CPU 密集型操作(如缩放)才真正受益于并发;I/O 密集部分靠并发提升有限批量图像处理真正的复杂点不在单张图的逻辑,而在于路径、格式、错误传播和资源复用之间的耦合。比如同一张图被反复 os.Open 三次(读取、解码、再读取元数据),或缩放后忘记 dst.Bounds() 没更新就传给下个环节——这类细节不会报错,但结果错得悄无声息。