用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写了同样的功能,三者一起比较。结果不得不令人叹服:

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

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

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

相关推荐
乐茵lin8 小时前
大厂都在问:如何解决map的并发安全问题?三种方法让你对答如流
开发语言·go·编程·map·并发安全·底层源码·sync.map
啥都想学点8 小时前
第18天:Springboot 项目搭建
java·spring boot·后端
Joker`s smile9 小时前
Spring Cloud Alibaba 基础入门实践
java·spring boot·后端·spring cloud
Victor3569 小时前
MongoDB(68)如何使用mongoexport和mongoimport?
后端
Victor3569 小时前
MongoDB(67)如何使用mongodump和mongorestore?
后端
散峰而望9 小时前
【数据结构】单调栈与单调队列深度解析:从模板到实战,一网打尽
开发语言·数据结构·c++·后端·算法·github·推荐算法
无籽西瓜a9 小时前
【西瓜带你学设计模式 | 第一期-单例模式】单例模式——定义、实现方式、优缺点与适用场景以及注意事项
java·后端·单例模式·设计模式
imuliuliang9 小时前
Spring Boot(快速上手)
java·spring boot·后端
yashuk9 小时前
Spring Boot 3.4 正式发布,结构化日志!
java·spring boot·后端
想打游戏的程序猿20 小时前
核心概念层——深入理解 Agent 是什么
后端·ai编程