并发目录大小报错

wmd_nb · 2022-07-24 15:45:36 · 1489 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2022-07-24 15:45:36 的主题,其中的信息可能已经有所发展或是发生改变。

改版了下书上的计算目录下所有总目录的文件大小,执行后小目录的可以跑出结果,但是根盘就不行,报错,求大佬指导

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


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

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

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