用Go写一个文件去重工具

文章首发于个人博客

背景

想自己做这个功能,主要是因为Duplicate Cleaner这个商业软件只有几天的试用时间,而且文件去重这个逻辑也非常简单。

{{}} graph TD a获取文件清单及大小 --> b按大小分组 --> c排除只有一个文件的组 --> d计算文件Hash值 --> e按Hash值分组 --> f排除只有一个文件的组 --> g选择需要删除的文件 --> h删除 {{}}

问题

计算文件Hash值,使用了hash.Hash接口,自然也用到了goroutine来缩短耗时,但是在测试的时候发现功能不太好用,时好时坏,准确说是有时能获取到重复列表,有时不能。

一点点排查,并且把代码段发给DeepSeek,最终确定是因为hash.Hash不是并发安全的。

修复方法很简单,只要在goroutine内实例化即可。修改之后达到了预期。

go 复制代码
func calcHashs(files []*FileInfo, hashName string) {
	g := sync.WaitGroup{}

	for _, file := range files {
		g.Add(1)
		go func(f *FileInfo) {
			defer g.Done()
			h := newHash(hashName)
			hashValue, err := calcHash(f.Path, h)
			if err != nil {
				log.Printf("计算文件 %s 的哈希值失败: %v", f.Path, err)
				return
			}
			f.Hash = hashValue
		}(file)
	}
	g.Wait()
}

TODO

以上存在一个隐患,即:当文件过多时,goroutine会爆炸,至于会有什么影响,没有进行测试,也没敢测试,担心把机器干翻。整体功能做完后,下一步进行这一处的优化。

题外话

计算Hash值这部分,专门准备了约15G的测试文件,和Duplicate Cleaner比较了一下,为此还用Lazarus写了同样的功能,三者一起比较。结果不得不令人叹服:

  • go和Lazarus的耗时非常接近,但Duplicate Cleaner只用了go和Lazarus一半的时间

  • go不同hash算法之间耗会有几十秒不等的差异,Duplicate Cleaner各算法耗时只有几秒的差异

看来收费果然是有收费的理由的!

相关推荐
Amos_Web5 分钟前
通过 Rspack 源码学 Rust(一):`mod`、`pub` 与 `use crate`/`use super`
后端
张彦峰ZYF17 分钟前
拆得开不等于该拆开:微服务与模块化单体的边界判据、规模阈值、团队适配与一致性代价
后端·微服务·边界是否稳定·扩展天花板是否到顶·有无小组能独立值班·独立部署的自由会否被用上·这一刀是否切断不可降级的不变量
是江迪呀29 分钟前
介绍一个开源项目 —— 烂笔头
前端·后端
captain37640 分钟前
Spring Web MVC(2)
java·前端·spring boot·后端·spring·mvc
紧跟先前的步伐41 分钟前
Go AI Agent 实战 17|模型适配层设计:让模型可替换
开发语言·人工智能·后端·ai·golang
IT_陈寒1 小时前
一文搞懂Java的核心概念
前端·人工智能·后端
铁皮饭盒1 小时前
workbuddy和codebuddy免费送1000积分, 10秒钟搞定
前端·后端
计算机就业还在扩大1 小时前
第2期-cmp.Ordered+类型推断+刻意未支持的特性
后端·面试·golang
王中阳Go10 小时前
两个入口答案不一致先别调模型:6 行入口口径对账表(附脚本)
人工智能·后端·python·大语言模型·1024程序员节
码事漫谈11 小时前
消除AI幻觉,普通人能做的五件事
后端