Scenario: Recently there was a requirement to fetch a specified amount of data such as 40 items from multiple sites. The following logic can be satisfied

  • When a coroutine has completed the specified number of fetching, other coroutine task fetching is stopped
  • When all tasks exceed the specified time and do not capture the specified amount of data, it will stop
  • If the specified amount of data is not captured after all tasks are executed, the result is returned immediately
package main import ( "fmt" "sync/atomic" "time" ) func main() { ch := make(chan int) taskDone := make(chan int32) d := make([]int, 0, 10) const limit = 40 var taskTotal int32 = 0 var taskCount int32 = 4 startTime := time.now () // Go func(chi chan< -int) {FMT.Println("start1, start1 ") for I := 0; i < 10; i++ { if taskTotal >= limit { close(chi) fmt.Println("len:", taskTotal) break } atomic.AddInt32(&taskTotal, // Complete a task minus one equals zero FMT.Println(" task 1ok:", TaskCount) taskDone < -taskCount}(ch) go func(chi chan< -int) {ftt. Println("start2") for I := 11; i < 20; i++ { if taskTotal >= limit { close(chi) fmt.Println("len2:", taskTotal) break } atomic.AddInt32(&taskTotal, Chi < -i} atomic.AddInt32(&taskCount, -1) FMT.Println(" task 2ok:", taskCount) taskDone <- taskCount }(ch) go func(chi chan<- int) { fmt.Println("start4") for i := 11; i < 20; i++ { if taskTotal >= limit { close(chi) fmt.Println("len2:", taskTotal) break } atomic.AddInt32(&taskTotal, Chi < -i} atomic.AddInt32(&taskCount, -1) FMT.Println(" taskCount :", taskCount) taskDone <- taskCount }(ch) go func(chi chan<- int) { fmt.Println("start3") for i := 21; i < 30; i++ { if taskTotal >= limit { close(chi) fmt.Println("len3:", taskTotal) break } atomic.AddInt32(&taskTotal, Chi < -i} atomic.AddInt32(&taskCount, -1) FMT.Println(" taskCount :", TaskCount) taskDone < -taskCount}(ch) for {select case v, ok := <-ch: // But it is possible that CH has no data. ok { goto OK } d = append(d, v) fmt.Println(".." , v, ok) case <-time.After(3 * time.Second): Println(" timeout ") close(ch) goto OK case taskDoneCount := <-taskDone: case taskDoneCount := <-taskDone: Println(" number of tasks ", taskDoneCount) if taskDoneCount == 0 {goto OK}} OK: fmt.Println(d, len(d), taskTotal, time.Since(startTime)) }Copy the code