Golang 协程正确的使用方法

错误的使用方法

package main
// 错误使用案例
import ("time""fmt"
)
var c1 chan string = make(chan string)
func main(){func(){time.Sleep(time.Second * 2)c1 <- "result 1"}()fmt.Println("c1 is", <-c1)
}

由于 c1 在创建时没有指定缓存长度, 所以在写入channel c1 时,必须应该有对应的接收端在等待,上例中,由于对c1的写入时c1 没有缓存区且没有接收端,所以就报错了。

fmt.Println("c1 is", <-c1)

这段代码本来是可以阻塞的,但是这种用法是错误的

正确的使用方法 (将写入放到单独的协程中)

通过将写入端放到单独的协程中,使得channel 的写入端和接收端可以对接。

// ....
func main(){go func(){time.Sleep(time.Second * 2)c1 <- "result 1"}()fmt.Println("I am here")fmt.Println("c1 is", <-c1)
}

可以看到 匿名函数部分代码是在独立的协程中执行的,在同一个协程中对一个channel写入时,如果channel 没有缓存长度,必然会报错,见错误案例

select 用法

select 可以同时监听多个channel

阻塞方式的

执行到select 语句时如果所有的case 中的channel 都没有数据,select 语句将会阻塞,直到一个case中的 channel 获取到数据。

package main
import ("time""fmt"
)func AskX(bid1 chan int) {for i:=100 ;i<105 ; i++{time.Sleep(time.Second*1)bid1 <- i}
}
func AskY(bid2 chan int) {for i:=0 ; i<5; i++{time.Sleep(time.Second*2)bid2 <- i}}func main(){bid1 := make(chan int)bid2 := make(chan int)go AskX(bid1)go AskY(bid2)select {case Xbid := <-bid1:fmt.Println(Xbid)case Ybid := <-bid2:fmt.Println(Ybid)}
}

运行的结果是,代码被阻塞 1秒后输出 100, 因为channel bid1 在1秒后拿到了数据,select 阻塞结束输出

不阻塞的

将阻塞部分 select 处代码修改为

    select {case Xbid := <-bid1:fmt.Println(Xbid)case Ybid := <-bid2:fmt.Println(Ybid)default :fmt.Println("no data.")}

可以看到只添加了 default 语句,表示当所有的 channel 都取不到数据时,默认执行 default 后面的语句

带超时机制的

   select {case Xbid := <-bid1:fmt.Println(Xbid)case Ybid := <-bid2:fmt.Println(Ybid)case <-time.After(time.Second*2):fmt.Println("overtime for 2 seconds")}

上面的代码表示,当所有channel 超过2秒还没有取到数据,就会执行超时设置部分的代码。

总结

  • 在同一个协程中如果对一个channel写入数据,如果channel 没有缓存长度,必然报错

  • 在主协程中有接收端,在子协程中没有发送端会报错

  • 在子协程中有发送端,在其他协程中没有接收端,不会报错

转载请注明:大后端 » Golang 协程正确的使用方法

Golang 协程的使用方法相关推荐

  1. golang 协程同步 简介

    目录 协程概念简要理解 为什么要做同步 协程的几种同步方法 Mutex channel WaitGroup 协程概念简要理解 协程类似线程,是一种更为轻量级的调度单位,但协程还是不同于线程的,线程是系 ...

  2. golang 数组 最后一个_面试必问:Golang高阶Golang协程实现原理

    1 01 引言 实现并发编程有进程,线程,IO多路复用的方式.(并发和并行我们这里不区分,如果CPU是多核的,可能在多个核同时进行,我们叫并行,如果是单核,需要排队切换,我们叫并发). 1.1 进程和 ...

  3. go 怎么等待所有的协程完成_怎么关闭golang协程

    怎么关闭golang协程 发布时间:2020-06-10 10:43:33 来源:亿速云 阅读:284 作者:Leah 这篇文章给大家分享的是关闭golang协程的方法.小编觉得挺实用的,因此分享给大 ...

  4. 深入浅出 Golang 协程池设计

    使用Go语言实现并发的协程调度池阉割版,本文主要介绍协程池的基本设计思路,目的为深入浅出快速了解协程池工作原理,与真实的企业协程池还有很大差距,本文仅供学习参考. 一.何为并发,Go又是如何实现并发? ...

  5. GoLang协程与通道---下

    GoLang协程与通道---下 新旧模型对比:任务和worker 惰性生成器的实现 实现 Futures 模式 复用 典型的客户端/服务器(C/S)模式 卸载(Teardown):通过信号通道关闭服务 ...

  6. golang协程分段下载文件

    目录 golang协程 加锁示例 golang协程分段下载文件 golang协程 golang协程分段下载文件,为了提升性能,更好的利用golang协程的特性,我们开始使用他测试一下我们的程序 gol ...

  7. Python与Golang协程异同

    背景知识 这里先给出一些常用的知识点简要说明,以便理解后面的文章内容. 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定 ...

  8. Python 中 异步协程 的 使用方法介绍

    静觅 崔庆才的个人博客:Python中异步协程的使用方法介绍:https://cuiqingcai.com/6160.html Python 异步 IO .协程.asyncio.async/await ...

  9. Golang 协程顺序打印

    Golang 协程顺序打印 A.B 两个协程分别打印 1.2.3.4 和 A,B,C,D 实现:定义 A.B 两个 channal,开 A.B 两个协程,A 协程输出[1, 2, 3, 4].B 协程 ...

最新文章

  1. C/C++中extern关键字详解
  2. Datawhale组队学习周报(第018周)
  3. eclipse 打开文件目录
  4. VTK:动轴用法实战
  5. 0 开场白元素项类的设计
  6. Pytest入门【1】
  7. scrapy爬虫实战分享
  8. 洛谷 刷题 深基部分题解(python版)-2022.01.29
  9. 01-jbpm工作流实现
  10. 读文万卷025期:使用MRI形态学特征和表观弥散系数预测WHO II/III级胶质瘤分子状态;帕金森病的中脑的定量磁敏感成像
  11. matlab中通过滤波器,[转载]matlab 滤波器(转)
  12. 企鹅撞冰块Java游戏_亲子桌面游戏玩具 拯救企鹅敲打冰块玩法
  13. Trie Tree和Radix Tree
  14. 微信公众号网页授权域名和JS接口安全域名配置攻略
  15. C算法之一元二次方程组的解
  16. 带劲!厂内全流程智能仓储物流系统
  17. python获取所有a股股票代码_股票量化分析(一)获取A股列表
  18. 1128_AURIX_TC275的基本参数了解
  19. Protobuf—简介,优缺点
  20. JS 各类验证(手机号验证、邮箱验证、身份证验证...)

热门文章

  1. java http服务_springboot官方例子中文翻译--RESTful服务启用CORS支持
  2. 计算机基础的算法思想
  3. 信息隐藏技术与应用期末复习
  4. Unity lightmap shader
  5. OpenGL 坐标变换(1)
  6. F1-VmwareCentOS7.x
  7. Linux命令解释之crontab
  8. 阿里云工程师用机器学习破解雾霾成因
  9. 喜欢就争取,得到就珍惜,错过就忘记—dbGet(二)
  10. protobuf使用错误总结