为了账号安全,请及时绑定邮箱和手机立即绑定

如何获取目录总大小?

如何获取目录总大小?

Go
LEATH 2021-11-08 14:31:10
所以我试图使用 Go 获取目录的总大小。到目前为止,我有这个:var dirSize int64 = 0func 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函数的范围内?
查看完整描述

3 回答

?
浮云间

TA贡献1829条经验 获得超4个赞

使用这样的全局充其量是不好的做法。如果DirSizeMB同时被调用,这也是一场比赛。


简单的解决方案是使用闭包,例如:


func DirSize(path string) (int64, error) {

    var size int64

    err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {

        if err != nil {

            return err

        }

        if !info.IsDir() {

            size += info.Size()

        }

        return err

    })

    return size, err

}

Playground


如果您认为这看起来更好,您可以将闭包分配给一个变量。


查看完整回答
反对 回复 2021-11-08
?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

如果你想使用一个变量,你可以这样做:


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

}


查看完整回答
反对 回复 2021-11-08
?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

您可以做的一件事是在 内部定义一个通道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 函数。虽然它可能会在给定路径上的所有文件上顺序调用它,但该实现理论上可以在单独的 goroutines 上同时调用其中的几个调用(如果有的话,文档可能会提到这一点)。无论如何,在为并发设计的语言中,确保您的代码安全是一种很好的做法。


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


查看完整回答
反对 回复 2021-11-08
  • 3 回答
  • 0 关注
  • 216 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信