import (
"fmt"
"io/fs"
"log"
"os"
"path/filepath"
"sync"
)
// WalkDir 外部调用的遍历目录统计信息的方法
func WalkDir(dirs ...string) string {
// 保证至少有一个目录需要统计遍历
// 默认当前目录
if len(dirs)==0{
dirs=[]string{"."}
}
// 初始化变量,channel用于完成Size的传递,WaitGroup用于等待调度
fileSizeCh:=make(chan int64,1)
wg:=&sync.WaitGroup{}
// 启动多个Goroutine统计信息,取决于len(dirs)
for _,dir:=range dirs{
wg.Add(1)
// 并发的编历统计每个目录的信息
go walkDir(dir,fileSizeCh,wg)
}
// 启动累计运算的Goroutine
// 1.用户关闭fileSizeCh
go func(wg *sync.WaitGroup) {
// 等待统计工作完成
wg.Wait()
// 关闭fileSizeCh
close(fileSizeCh)
}(wg)
// 2,range的方式从fileSizeCh中获取文件大小
// 3. 统计结果,使用channel传递出来
fileNumCh:=make(chan int64,1)
sizeTotalCh:=make(chan int64,1)
go func(fileSizeCh <-chan int64,fileNumCh,sizeTotalCh chan<- int64) {
// 统计文件数,和文件整体大小
var fileNum,sizeToTal int64
// 遍历全部的filesizeCh元素,统计文件数量和大小,直到channel被关闭
for filesize:=range fileSizeCh{
// 累计文件数,和统计文件整体大小
fileNum++
sizeToTal+=filesize
}
// 将统计结果发送到对应的channel中
fileNumCh<-fileNum
sizeTotalCh<-sizeToTal
}(fileSizeCh,fileNumCh,sizeTotalCh)
// 整理返回值
// size 的单位是Byte
// 需要的单位是 MB
result:=fmt.Sprintf("%d files %.2f MB\n",<-fileNumCh,float64(<-sizeTotalCh)/1e6)
return result
}
// 遍历并统计某个目录的信息
// 核心实现函数,完成递归,统计等
func walkDir(dir string,fileSizeCh chan<-int64,wg *sync.WaitGroup) {
// 一:wg的计数器减少
defer wg.Done()
// 二:读取dir下的全部文件信息,并遍历
for _,fileinfo:=range fileInfos(dir){
// 三:根据dir下的文件信息
if fileinfo.IsDir(){
// 1.如果目录,递归获取信息
// 子目录地址
subDir:=filepath.Join(dir,fileinfo.Name())
// 递归调用,阳是并发的,也需要wg统计
wg.Add(1)
go walkDir(subDir,fileSizeCh,wg)
}else{
// 2.如果不是,就是文件,统计文件大小,放入channel
fileSizeCh<-fileinfo.Size()
}
}
}
// 获取某个目录下的文件信息列表
func fileInfos(dir string)[]fs.FileInfo {
// 1.读取目录的全部文件
entries,err:=os.ReadDir(dir)
if err!=nil{
log.Println("WalkDir error:",err)
return []fs.FileInfo{}
}
// 2.如获取文件的文件信息
// DirEntry to FileInfo
infos:=make([]fs.FileInfo,0,len(entries))
for _,entry:=range entries{
// 如果获取文件信息无错误,存储到Infos中
if info,err:=entry.Info();err==nil{
infos=append(infos,info)
}
}
// 3.返回
return infos
}
GO并发统计文件大小
lisus20072026-03-13 16:53
相关推荐
颜进强2 分钟前
04 - 一张图看懂 OpenSpec 变更的一生:从创建到归档Cobyte3 分钟前
Claude Code 的 Task System 的实现原理小强19883 分钟前
useEffect 完整使用指南:依赖数组、闭包陷阱、清理函数实战智驭未来掌门人3 分钟前
在windows下快速搭建go2rtc流媒体平台大白8016 分钟前
为什么不要滥用 useMemo 和 useCallback?过度优化反而更卡萧瑟余晖37 分钟前
Java深入解析篇三十六之分布式系统详解神奇小汤圆1 小时前
Codex 子 Agent 配置指南:让 Sol 当军师,Luna 当搬砖工ClouGence1 小时前
2026 年 4 款数据库管理工具推荐:免费、开源、付费怎么选?ZJU_统一阿萨姆1 小时前
【推理优化进阶】调度器的数学内核:排队论、SLO 与在线决策大勇前进1 小时前
React 中 State 为什么不能直接修改?很多新手一直没懂