我的程序将多个文件和目录从计算机的不同部分复制到一个地方。
其中一个目录很大,所以复制它大约需要20-30秒。现在我只是制作了这个方法,它复制该目录以作为 goroutine 启动:
func CopySpecificDirectory(source, dest string, quit chan int) (err error) {
files, err := os.Open(source)
file, err := files.Readdir(0)
if err != nil {
fmt.Printf("Error reading directory %s: %s\n", source, err)
return err
}
for _, f := range file {
if f.IsDir() {
copy.CopyDir(source+"\\"+f.Name(), dest+"\\"+f.Name())
} else {
copy.CopyFile(source+"\\"+f.Name(), dest+"\\"+f.Name())
}
}
quit <- 1
return nil
}
主要:
quit := make(chan int)
go CopySpecificDirectory(config.Location+"\\Directory", config.Destination, quit)
这只是将我的程序改进了几秒钟。在我的 CopySpecificDirectory 方法中(如果这是最好的方法)我想为每个目录创建一个 goroutine,可能是这样的:
c := make(chan int)
for _, f := range file {
if f.IsDir() {
go func() {
copy.CopyDir(source+"\\"+f.Name(), dest+"\\"+f.Name())
c <- 1
}()
} else {
copy.CopyFile(source+"\\"+f.Name(), dest+"\\"+f.Name())
}
}
使用这种方法,我不知道在哪里等待每个目录的复制完成 (<- c)。
这是最好的方法吗?如果有人有其他建议,复制目录的最快方法是什么,我很乐意听取。
编辑:
我使用了来自网站的 sync.WaitGroup 示例的方法。
for _, f := range file {
if f.IsDir() {
wg.Add(1)
go func() {
defer wg.Done()
copy.CopyDir(source+"\\"+f.Name(), dest+"\\"+f.Name())
}()
// more code
我已将 var wg sync.WaitGroup
声明为全局,并且在我调用 CopySpecificDirectory
后立即在 main 中执行 wg.Wait()
.
但是 CopySpecificDirectory
在复制所有内容之前完成。我究竟做错了什么 ?看起来它没有等待 goroutines 完成。
最佳答案
使用sync.WaitGroup()
而不是 channel :
- 创建一个 WaitGroup 对象。
- 在产生一个 goroutine 之前,
Add()
一个给它。 - 当一个 goroutine 即将退出时,它会对该对象调用
Done()
。 - 在您的主(等待)代码中,对该对象调用
Wait()
。一旦所有以这种方式“跟踪”的 goroutine 完成执行,此函数将返回。
请注意,您的程序是 I/O 绑定(bind)的,而不是 CPU 绑定(bind)的。如果您的代码需要将文件从物理上不同的设备复制到(其他)物理上不同的设备,您可以节省一些时间。如果你只是在同一个文件系统上移动文件,或者你所有的源都在同一个文件系统上,或者你所有的目的地都在同一个文件系统上,你不会得到太多,因为你的 goroutines 只会竞争单个共享资源— 存储设备 — 最终结果与您只是按顺序执行复制操作时的情况不会有太大不同。
举个例子,/etc/fstab
文件的手册页包含有关经典 Unix 系统上已挂载/可挂载文件系统的信息,其中提到操作系统从不检查位于同一物理介质上的文件系统同时 - 仅按顺序进行,同时它会并行检查位于不同驱动器上的文件系统。请参阅 manual page 中的 fs_passno
参数条目.
关于go - 使用 goroutines 复制子目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21459457/