加入收藏 | 设为首页 | 会员中心 | 我要投稿 马鞍山站长网 (https://www.0555zz.cn/)- 媒体处理、内容创作、云渲染、网络安全、业务安全!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

go channel基本使用

发布时间:2023-10-19 12:35:57 所属栏目:语言 来源:
导读:Go 程序在并发处理一些任务的时,会为每一个任务创建一个 goroutine,然后需要根据不同的 goroutine 的返回的结果做不同的处理。
如果按照通常的做法,分别获取每个 channel 的结果:

taskCh1 := make(chan bool
Go 程序在并发处理一些任务的时,会为每一个任务创建一个 goroutine,然后需要根据不同的 goroutine 的返回的结果做不同的处理。
如果按照通常的做法,分别获取每个 channel 的结果:

taskCh1 := make(chan bool)
taskCh2 := make(chan bool)
taskCh3 := make(chan bool)

go run(taskCh1)
go run(taskCh2)
go run(taskCh3)

for {
   // 接收通道 1 的结果
   result1 := <-taskCh1
   // 接收通道 2 的结果
   result2 := <-taskCh2
   // 接收通道 3 的结果
   result3 := <-taskCh3
}
然后再根据不同 goroutine 返回的结果做后续的处理,这个代码有个问题,需要等待所有的 goroutine 都执行完成之后才能做出结果,这样实现的效率很低,因为每一个获取 channel 值的过程都是阻塞的。
在处理多个通道时,想同时接收多个通道的数据将会变的很困难。
而且在一些情况下,需要根据先返回通道的做出不同的处理,上面那种方式无法做到,这就需要使用多路复用。

Go 提供了 select 机制来解决这个问题。

select 基本使用
select 语法形式和 switch 很相似,switch 接收一个变量,然后根据变量的值做不同的处理,select 操作接收的是通道操作:

ch := make(chan int, 1) // 这个例子中,这里必须用缓冲通道

for {
    select {
    case <-ch:
        time.Sleep(time.Second)
        fmt.Println("case 1 invoke")
    case data := <-ch:
        time.Sleep(time.Second)
        fmt.Printf("case 2 invoke %d\n", data)
    case ch <- 100:
        time.Sleep(time.Second)
        fmt.Println("case3 invoke")
}
在 select 的 case 中,可以执行三种操作:

<- ch:接收通道,但是对值不处理
data := <-ch:接收通道,并处理从通道中得到的结果
ch <- 100:向通道中发送数据

上面的程序运行起来之后,case 3 会首先执行,然后 case1 和 case2 会随机执行一个,程序就这样一直交替运行下去。
如果用 select 改造上面第一个例子中的代码,就是下面这样:

for {
        select {
        // 接收通道 1 的结果
        case r := <-taskCh1:
            fmt.Printf("task1 result %+v\n", r)
        // 接收通道 2 的结果
        case r := <-taskCh2:
            fmt.Printf("task2 result %+v\n", r)
        // 接收通道 3 的结果
        case r := <-taskCh3:
            fmt.Printf("task3 result %+v\n", r)
        }
}
select 会及时响应每一个就绪的 channel,无论是发送数据还是接收数据。
 

(编辑:马鞍山站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章