dqayok7935 2014-01-30 14:40
浏览 2
已采纳

使用goroutines复制子目录

My program copies multiple files and directories from different parts of the computer to one place.

One of the directories is very big, so it takes about 20-30 seconds to copy it. For now I just made this method which copies that directory to start as a 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
", 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
}

Main:

quit := make(chan int)
go CopySpecificDirectory(config.Location+"\\Directory", config.Destination, quit)

This just improves my program by a few seconds. Inside my CopySpecificDirectory method (if this is the best way) I want for each directory to create a goroutine, something like this maybe:

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())
    }
}

With this approach I don't know where to wait for the copy to finish for every directory (<- c).
Is this the best way ? If anyone has other suggestion what is the fastest way to copy a directory, I will love to hear it.

edit:

I used the aproach form the example of sync.WaitGroup from the website.

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

I have declared var wg sync.WaitGroup as global, and I do wg.Wait() in main right after I call CopySpecificDirectory.

But CopySpecificDirectory finishes before copying all the contents. What am I doing wrong ? Looks like it is not waiting for the goroutines to finish.

  • 写回答

3条回答 默认 最新

  • douchuang1852 2014-01-30 15:23
    关注

    Use sync.WaitGroup() instead of channels:

    1. Create a wait group object.
    2. Before spawning a goroutine, Add() one to it.
    3. When a goroutine is about to quit, it calls Done() on that object.
    4. In your main (waiting) code, call Wait() on that object. This function will return once all the goroutines "tracked" this way finish their execution.

    Note that your program is I/O bound, not CPU-bound. You could save some time if your code would need to copy files from physically different devices to (other) physically different devices. If you're just shuffling files around on the same filesystem, or all your sources are on the same filesystem, or all your destinations are on the same filesystem, you won't gain much as your goroutines would just compete over the single shared resource—the storage device—and the end result won't be much more different from the case when you were just executing copying operations sequentially.

    To provide an example, the manual page for the /etc/fstab file which contains information on mounted/mountable filesystems on classic Unix systems mentions that the OS never checks filesystems located on the same physical medium at the same time—only sequentially, while at the same time it would check filesystems located on different drives in parallel. See the entry for the fs_passno parameter in the manual page.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 正弦信号发生器串并联电路电阻无法保持同步怎么办
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 个人网站被恶意大量访问,怎么办
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM
  • ¥15 划分vlan后不通了
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)