戈朗通道缺少一些值

我有以下代码


package main


import (

    "fmt"

    "math/rand"

    "time"

)


func main() {

    concurrent := 12

    ch := make(chan int)

    defer close(ch)

    for i := 1; i <= concurrent; i++ {

        go worker(i, ch)

    }

    for i := 1; i <= 21; i++ {

        ch <- i

    }

}


func worker(worker int, ch chan int) {

    for requestId := range ch {

        fmt.Printf("worker %d is requesting to %d...\n", worker, requestId)

        time.Sleep(time.Duration(rand.Intn(3)) * time.Second)

    }

}

该函数启动运行该函数的多个 goroutine,然后将一些值放入通道中,这些值由 worker 打印。我的问题是,有时通道中的最后一个值甚至更多值不是由工作人员打印的。mainworker


worker 10 is requesting to 10...

worker 5 is requesting to 1...

worker 5 is requesting to 13...

worker 7 is requesting to 6...

worker 2 is requesting to 2...

worker 3 is requesting to 7...

worker 3 is requesting to 14...

worker 6 is requesting to 4...

worker 11 is requesting to 9...

worker 9 is requesting to 8...

worker 9 is requesting to 15...

worker 12 is requesting to 11...

worker 8 is requesting to 12...

worker 8 is requesting to 16...

worker 4 is requesting to 5...

worker 1 is requesting to 3...

worker 11 is requesting to 17...

我认为这是因为主要功能在打印最后一个值之前结束并“杀死”所有运行goroutine,因为最后所有值都始终被打印出来。


func main() {

    concurrent := 12

    ch := make(chan int)

    defer close(ch)

    for i := 1; i <= concurrent; i++ {

        go worker(i, ch)

    }

    for i := 1; i <= 21; i++ {

        ch <- i

    }

    time.Sleep(3 * time.Second)

}

如何在不使用睡眠的情况下解决此问题,并且如果可能的话仅使用通道?


摇曳的蔷薇
浏览 103回答 1
1回答

RISEBY

因为主 goroutine 在最后一个循环之后立即退出,导致整个程序也退出,所以后台 goroutines 可能会也可能不会有机会运行,你必须提供一些同步方法来“等待”所有工作线程完成。for用sync.WaitGroup&nbsp; &nbsp;func main() {&nbsp; &nbsp; concurrent := 12&nbsp; &nbsp; ch := make(chan int)&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; for i := 1; i <= concurrent; i++ {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go func(i int) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; worker(i, ch)&nbsp; &nbsp; &nbsp; &nbsp; }(i) // You have to pass i as parameter&nbsp; &nbsp; }&nbsp; &nbsp; for i := 1; i <= 21; i++ {&nbsp; &nbsp; &nbsp; &nbsp; ch <- i&nbsp; &nbsp; }&nbsp; &nbsp; close(ch) // Close channel to tell all workers to stop&nbsp; &nbsp; wg.Wait() // Wait all workers to finish its work&nbsp; &nbsp;}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go