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
如果您认为这看起来更好,您可以将闭包分配给一个变量。
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
}
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 函数以确定的顺序运行文件,因此他的解决方案足以解决这个问题,但我将把它作为一个示例,说明如何确保同时运行内部函数的安全。
- 3 回答
- 0 关注
- 216 浏览
添加回答
举报