如何获取目录总大小?

时间:2015-09-09 14:43:38

标签: go

所以我试图使用golang获取目录的总大小,到目前为止我有这个

var dirSize int64 = 0

func readSize(path string, file os.FileInfo, err error) error {
    if !file.IsDir() {
        dirSize += file.Size()
    }
    return nil
} 

func DirSizeMB(path string) float64 {
    dirSize = 0
    filepath.Walk(path, readSize)
    sizeMB := float64(dirSize) / 1024.0 / 1024.0
    sizeMB = Round(sizeMB, .5, 2)
    return sizeMB
}

所以问题是dirSize全局变量是否会导致问题,如果是,我如何将其移动到DirSizeMB函数的范围?

2 个答案:

答案 0 :(得分:0)

如果要使用变量,可以执行以下操作:

func DirSizeMB(path string) float64 {
    var dirSize int64 = 0

    readSize := func(path string, file os.FileInfo, err error) error {
        if !file.IsDir() {
            dirSize += file.Size()
        }

        return nil
    }

    filepath.Walk(path, readSize)    

    sizeMB := float64(dirSize) / 1024.0 / 1024.0

    return sizeMB
}

答案 1 :(得分:-3)

您可以做的一件事是在DirSizeMB内定义一个通道,并在该函数内部定义readSize,以便将通道作为闭包。然后将所有尺寸发送出频道,并在收到时将它们相加。

func DirSizeMB(path string) float64 {
    sizes := make(chan int64)
    readSize := func(path string, file os.FileInfo, err error) error {
        if err != nil || file == nil {
            return nil // Ignore errors
        }
        if !file.IsDir() {
            sizes <- file.Size()
        }
        return nil
    }

    go func() {
        filepath.Walk(path, readSize)
        close(sizes)
    }()

    size := int64(0)
    for s := range sizes {
        size += s
    }

    sizeMB := float64(size) / 1024.0 / 1024.0

    sizeMB = Round(sizeMB, 0.5, 2)

    return sizeMB
}

http://play.golang.org/p/zzKZu0cm9n

为什么要使用频道?

除非您已阅读底层代码,否则您实际上并不知道filepath.Walk如何调用您的readSize函数。虽然它可能在给定路径上的所有文件上按顺序调用它,但实际上理论上可以在单独的goroutine上同时调用其中几个调用(如果文件确实如此,文档可能会提到它)。无论如何,在为并发性设计的语言中,确保代码安全是一种很好的做法。

@DaveC给出的答案显示了如何通过对局部变量使用闭包来解决具有全局变量的问题,因此多次同时调用DirSize是安全的。 Docs for Walk明确声明walk函数以确定的顺序运行文件,因此他的解决方案足以解决这个问题,但我将此作为如何使其安全地同时运行内部函数的示例