并发目录大小报错

wmd_nb · · 898 次点击 · 开始浏览    置顶

改版了下书上的计算目录下所有总目录的文件大小,执行后小目录的可以跑出结果,但是根盘就不行,报错,求大佬指导 ``` import ( "fmt" "os" "path/filepath" "sync" "time" ) var done = make(chan struct{}) func cancelled() bool { select { case <-done: return true default: return false } } func main() { // Determine the initial directories. roots := os.Args[1:] if len(roots) == 0 { roots = []string{"."} } go func() { os.Stdin.Read(make([]byte, 1)) // read a single byte close(done) }() fileSizes := make(chan map[string]int64) var n sync.WaitGroup for _, root := range roots { n.Add(1) go walkDir(root, &n, fileSizes) } go func() { n.Wait() close(fileSizes) }() tick := time.Tick(500 * time.Millisecond) var nbytes = make(map[string]int64) loop: for { select { case <-done: // Drain fileSizes to allow existing goroutines to finish. for range fileSizes { // Do nothing. } return case size, ok := <-fileSizes: if !ok { break loop // fileSizes was closed } for k, v := range size { nbytes[k] += v } case <-tick: //printDiskUsage(nfiles, nbytes) } } for k, v := range nbytes { if v > 10*1e9 { printDiskUsage(k, v) // final totals } } } func printDiskUsage(nfiles string, nbytes int64) { fmt.Printf("【%s】:【%.1f GB】\n", nfiles, float64(nbytes)/1e9) } func walkDir(dir string, n *sync.WaitGroup, fileSizes chan<- map[string]int64) { dirsSize := make(map[string]int64) //需要有个缓冲,不然并发报错 defer n.Done() if cancelled() { return } for _, entry := range dirents(dir) { if entry.IsDir() { n.Add(1) subdir := filepath.Join(dir, entry.Name()) go walkDir(subdir, n, fileSizes) } else { dirsSize[dir] += entry.Size() } fileSizes <- dirsSize } } var sema = make(chan struct{}, 20) // concurrency-limiting counting semaphore func dirents(dir string) []os.FileInfo { select { case sema <- struct{}{}: // acquire token case <-done: return nil // cancelled } defer func() { <-sema }() // release token f, err := os.Open(dir) if err != nil { fmt.Fprintf(os.Stderr, "du: %v\n", err) return nil } defer f.Close() entries, err := f.Readdir(0) // 0 => no limit; read all entries if err != nil { fmt.Fprintf(os.Stderr, "du: %v\n", err) // Don't return: Readdir may return partial results. } return entries } ``` ![企业微信截图_5d112c50-e290-4b2f-a66a-56458d21cd43.png](https://static.golangjob.cn/220724/535fee11a1ea9443f6623e040eb3c9c7.png)

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

898 次点击  
加入收藏 微博
3 回复  |  直到 2022-07-27 14:07:54
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传