我有大量的目录,每个目录都包含数百到数千个文件.我想遍历目录列表.然后 for each 目录调用Go routine ,该 routine 将扫描目录中的文件,并将每个文件的路径添加到作业(job)队列,以供一组要处理的作品使用.

这就是我到目前为止所拥有的:

type AppConfig struct {
    UploadPath string `mapstructure:"upload_path"`
    LocalPath  string `mapstructure:"local_path"`
    Bucket     string `mapstructure:"bucket"`
}

func consumer(i int, jobs <-chan *ops.Job) {
    defer wg.Done()
    for job := range jobs {
        fmt.Printf("Worker: %v is processing file: %v\n", i, job.Work)
    }
}

func producer(jobs chan<- *ops.Job, filesToTransfer []string) {
    for i, file := range filesToTransfer {
        jobs <- &ops.Job{Id: i, Work: file}
    }
}

func main() {
    var (
        appconfigs map[string]*ops.AppConfig
        wg *sync.WaitGroup
    )

    jobs := make(chan *ops.Job)

    // setting up workers
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go consumer(i, jobs)
    }

    // adding jobs
    for _, values := range appconfigs {
        filesToTransfer := ops.ScanUploadPath(values.LocalPath)
        go producer(jobs, filesToTransfer)

    }

    go func() {
        wg.Wait()
        close(jobs)
    }()
}

之前,当我在producer函数中调用close(jobs)时,我在关闭通道问题上遇到了死锁和panic .我读到我应该把这个放在我的main()号上:

go func() {
        wg.Wait()
        close(jobs)
}()

我真的不明白为什么我需要在我的producer之外还有一个单独的围棋程序.我希望有人能解释一下原因.

推荐答案

由于程序在Main函数返回时退出,因此将调用移动到Goroutine会掩盖该问题.

使用以下代码:

// Start workers.
var wg sync.WaitGroup
jobs := make(chan *ops.Job)
for i := 0; i < 10; i++ {
    wg.Add(1)
    go consumer(&wg, i, jobs)
}

// Send jobs to the workers.
for _, values := range appconfigs {
    filesToTransfer := ops.ScanUploadPath(values.LocalPath)

    // Send the jobs from the main goroutine.
    // Nothing is gained by using a goroutine
    // as in the question.
    for i, file := range filesToTransfer {
        jobs <- &ops.Job{Id: i, Work: file}
     }
}

// Close the channel to signal that all jobs are
// sent.
close(jobs)

// Wait for the workers to complete.
wg.Wait()

Go相关问答推荐

gorm如何声明未自动更新的unix时间戳米尔斯字段

读取JSON数据并在网页上显示

由docker中的nginx提供的样式和图像在页面上不起作用

如何在链接中写入链接

如何使用 Go 连接到非默认 firestore 数据库?

如何修复 Go 中协议缓冲区定义中重新定义的字段?

从文件读取字节,将其保存到 struct 体并修改值

使用Cookie身份验证的Gorilla Golang Websocket优化

如何将任何类型的数据值传递到 Golang 中的 GRPC Protobuf struct ?

我无法使用反向代理更改主机标头

MQTT 客户端没有收到另一个客户端发送的消息

如何将 base64 编码的公钥转换为 crypto.PublicKey 或 ecdsa.PublicKey

也许在 golang 中包(字符串和字符串类型不匹配)

Gorm delete with clauses sqlmock 测试

Go 信号处理程序不处理终端窗口关闭

将 big.Int 转换为 [2]int64,反之亦然和二进制补码

切片到数组指针的转换

Go 加密库创建的 PKCS1 公钥与openssl rsa ...之间的区别

Go lang - 惯用的默认后备

Go:为一组单个结果实现 ManyDecode