golang channel 怎么判断是否读取完成?

    r := make(chan int)
    for n := 0; n < 100000; n++ {
        go func(x int, r chan int) {
                if x%3 == 0 && x%23 == 0{
                    r <- x
                }
        }(n, r)
    }

for i := range r {
    println(i) 
} 

上面的代码报错。

而我又不知道channel 的个数,那么我怎么知道,什么时候,并发执行结束了呢?

求指教

阅读 13.4k
4 个回答
import "sync"
    
func main() {
    rNum := 100000
    r := make(chan int, rNum)
    var wg sync.WaitGroup
    for n := 0; n < rNum; n++ {
        wg.Add(1)
        go func(x int, r chan int) {
            defer wg.Done()
            if x%3 == 0 && x%23 == 0 {
                r <- x
            }
        }(n, r)
    }

    wg.Wait()
    close(r)                           
    for i := range r {
        println(i)
    }
}
package main

import (
    "sync"
)

func main() {

    wait := sync.WaitGroup{}
    r := make(chan int)
    for n := 0; n < 100000; n++ {
        wait.Add(1)
        go func(x int, r chan int) {
            defer wait.Done()
            if x%3 == 0 && x%23 == 0 {
                r <- x
            }
        }(n, r)
    }
    go func() {
        wait.Wait()
        close(r)
    }()

    for i := range r {
        println(i)
    }

}

预先不知道channel里消息会有多少的话,我认为可以通过判断超时的方式来进行判断
因为这里定义的是无缓冲channel,所以第一个for循环必须启一个协程,要不然就阻塞在那里了

func main(){
    r := make(chan int)
    go func() {
        for n := 0; n < 100000; n++ {
            go func(x int, r chan int) {
                if x%3 == 0 && x%23 == 0{
                    r <- x
                }
            }(n, r)
        }
    }()

    for{
        select {
            case i := <- r:
                fmt.Println(i)
            case <- time.After(time.Second*3):
                fmt.Printf("time out")
                goto out
        }
    }
out:
    fmt.Printf("end")
}

也可以加一个chan来判断结束,不过并没有验证严谨性,仅供参考

func main(){
    r := make(chan int)
    quit := make(chan int)
    go func() {
        for n := 0; n < 100000; n++ {
            go func(x int, r chan int) {
                if x%3 == 0 && x%23 == 0{
                    r <- x
                }
            }(n, r)
        }
        quit <- 1
    }()

    for{
        select {
            case i := <- r:
                fmt.Println(i)
            case <- quit:
                fmt.Println("quit")
                goto out
        }
    }
out:
    fmt.Printf("end")
}

首先题目中只有一个channel
所有启动的goroutine作为发送者,主程序作为接收者。他们共享了这一个channel

在go关键字启动的所有的goroutine发送完毕后,即会退出。
只剩下主程序的for...range循环还在试图从channel接收数据,因此造成deadlock报错。

解决问题:只需要所有的goroutinue(发送端)执行完毕后,关闭channel。

close(r)

何时所有的goroutinue执行完毕就需要另行判断了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏