go - 对于选择组问题

标签 go select concurrency channels

我正在尝试编写一个函数来执行多个作业,当所有作业完成后,我希望控件在 wg.Wait() 之后进行。我已经提到了不同的问题,我在代码的注释中面临。

我怎样才能让它工作?

func (q *ChanExecutor) Perform(ctx context.Context, name string, taskData *interface{}) chan *job.JobResult {
    var waitgroup sync.WaitGroup
    waitgroup.Add(1)
    go func(wg *sync.WaitGroup) {
        for j := range q.jobCh { // This is the channel which gives jobs
            wg.Add(1)
            go func(qq *ChanExecutor, jVal job.Job) { // we are just passing these values to closure. Is this necessary?
                jobResultChannel:= jVal.Do(ctx) // Here we are executing the job as result which sends another channel of results
                donech := jVal.DoneCh() // Job returns another channel which tells if that job is done
                for true {
                    select {
                    case res := <-jobResultChannel:
                        q.result <- res // From the result we are passing that result to another channel
                    case syncJobDone := <-donech:
                        if syncJobDone {
                            donech = nil // here if the donech receives true it should come out of the select and for loop and the goroutine. How to do that?
                            // Another thing here, if the donech returns true before jobResultChannel then it should still go to jobResultChannel's case block
                            // The jVal.Do(ctx) executes the job and returns channel but in my case before starting the forloop both channels has values and donech has true value
                            wg.Done()
                            break
                        }
                    }
                }
            }(q, *j)
        }
    }(&waitgroup)
    go func(wg *sync.WaitGroup, qq *ChanExecutor) {
        time.Sleep(200 * time.Millisecond) // Here is another blunder. If I don't sleep here, randomly, it goes after wg.Wait()
        // even though all the jobs are not done.
        wg.Done() // REmoving the one which was added immediately after creating wg instance.
        wg.Wait()
        fmt.Println("Wait finish")
        qq.Done()
    }(&waitgroup, q)
    fmt.Printf("returning result channel not result")
    return q.result
}

最佳答案

首先,您应该删除 sleep 和 wg.Done从第二个 goroutine 开始。它有时会在没有 sleep 的情况下失败,因为有时第一个 goroutine 没有机会添加到 wg在第二个删除它之前。

其次,您正在尝试终止 goroutine,因此请执行以下操作:

if syncJobDone {
   wg.Done()
   return
}

关于go - 对于选择组问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61216771/

相关文章:

csv - 如何在logrus中隐藏日志级别和时间

mysql - 在mysql中创建存储过程以在每个批处理中生成卷号

php - 使用bind_param、prepare语句和fetch从数据库获取结果不起作用

java - 使用 3 个 PetersonLock 的数组来同步 4 个进程

concurrency - 并发 slice 访问

postgresql - PostgreSQL 的这个通用 MERGE/UPSERT 函数安全吗?

go - 禁止在 golang 内联

go - 如何将字节数组传递给接受字节 slice 的函数?

go - 将 firestore "integer_value"转换为整数

mysql - mysql 如何在一行中显示具有相同 id 的多行?