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
相关推荐
Memory_荒年2 小时前
限流算法:当你的系统变成“网红景点”,如何避免被游客挤垮?我命由我123452 小时前
Git 问题:Author identity unknown*** Please tell me who you are.AskHarries2 小时前
网站被人疯狂爬了 1.5TB 流量梦游钓鱼2 小时前
Logger.h和Logger.cc文件分析xiaoye37082 小时前
Spring 内置注解 和自定义注解的异同CRMEB系统商城2 小时前
CRMEB标准版系统(PHP)v6.0公测版发布,商城主题市场上线~yangminlei2 小时前
openclaw对接飞书6+h2 小时前
【Spring】Service层常用注解详解临溟夜空的繁星3 小时前
C++ STL-- vector