通道(channel)是用来传递数据的一个数据结构。

通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。

ch <- v    // 把 v 发送到通道 ch
v := <-ch  // 从 ch 接收数据// 并把值赋给 v

声明一个通道很简单,我们使用chan关键字即可,通道在使用前必须先创建:

ch := make(chan int)

注意:默认情况下,通道是不带缓冲区的。发送端发送数据,同时必须有接收端相应的接收数据。

以下实例通过两个 goroutine 来计算数字之和,在 goroutine 完成计算后,它会计算两个结果的和:

实例

package mainimport "fmt"func sum(s []int, c chan int) {sum := 0for _, v := range s {sum += v}c <- sum // 把 sum 发送到通道 c
}func main() {s := []int{7, 2, 8, -9, 4, 0}c := make(chan int)go sum(s[:len(s)/2], c)go sum(s[len(s)/2:], c)x, y := <-c, <-c // 从通道 c 中接收fmt.Println(x, y, x+y)
}

输出结果为:

-5 17 12

通道缓冲区

通道可以设置缓冲区,通过 make 的第二个参数指定缓冲区大小:

ch := make(chan int, 100)

带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放在缓冲区里面,可以等待接收端去获取数据,而不是立刻需要接收端去获取数据。

不过由于缓冲区的大小是有限的,所以还是必须有接收端来接收数据的,否则缓冲区一满,数据发送端就无法再发送数据了。

注意:如果通道不带缓冲,发送方会阻塞直到接收方从通道中接收了值。如果通道带缓冲,发送方则会阻塞直到发送的值被拷贝到缓冲区内;如果缓冲区已满,则意味着需要等待直到某个接收方获取到一个值。接收方在有值可以接收之前会一直阻塞。

实例

package mainimport "fmt"func main() {// 这里我们定义了一个可以存储整数类型的带缓冲通道// 缓冲区大小为2ch := make(chan int, 2)// 因为 ch 是带缓冲的通道,我们可以同时发送两个数据// 而不用立刻需要去同步读取数据ch <- 1ch <- 2// 获取这两个数据fmt.Println(<-ch)fmt.Println(<-ch)
}

执行输出结果为:

1
2

Go 遍历通道与关闭通道

Go 通过 range 关键字来实现遍历读取到的数据,类似于与数组或切片。格式如下:

v, ok := <-ch

如果通道接收不到数据后 ok 就为 false,这时通道就可以使用 close() 函数来关闭。

实例

package mainimport ("fmt"
)func fibonacci(n int, c chan int) {x, y := 0, 1for i := 0; i < n; i++ {c <- xx, y = y, x+yfmt.Println("aaa")}close(c)
}func main() {c := make(chan int, 10)go fibonacci(cap(c), c)// range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个// 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据// 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不// 会结束,从而在接收第 11 个数据的时候就阻塞了。for i := range c {fmt.Println(i)}
}

执行输出结果为:

0
1
1
2
3
5
8
13
21
34

Golang通道(chan,协程交互数据)相关推荐

  1. Go语言 有缓冲通道、协程池

    文章目录 导言 有缓冲通道.线程池 有缓冲通道是什么? 例子 另一个例子 死锁 容量 vs 长度 WaitGroup 实现协程池 1. 创建数据结构 2. 创建相关函数 1. `digits`函数 2 ...

  2. Go学习笔记 -- 通道实现协程等待

    文章目录 前言 方法一:睡眠等待 方法二:通道 什么是通道? 通道的特性 什么是非缓冲通道 什么是缓冲通道 通道的简单使用 非缓冲通道 缓冲通道 小心死锁 使用通道实现协程等待 前言 上一次简单了解了 ...

  3. golang中通知协程退出的方式

    1 需求分析 go语言中通知子 goroutine 退出的三种方式 方式1 通过全局变量:如果全局变量为真就退出 方式2 通过通道:协程在通道里面取到true就退出 方式3 通过context:通过调 ...

  4. golang实现多协程下载文件(支持断点续传)

    golang实现多协程下载文件(支持断点续传) 引言 写这篇文章主要是周末休息太无聊,看了看别人代码,发现基本上要么是多协程下载文件要么就只有单协程的断点续传,所以就试了试有进度条的多协程下载文件(支 ...

  5. Golang —— goroutine(协程)和channel(管道)

    协程(goroutine) 协程(goroutine)是Go中应用程序并发处理的部分,它可以进行高效的并发运算. 协程是轻量的,比线程更廉价.使用4K的栈内存就可以在内存中创建. 能够对栈进行分割,动 ...

  6. golang内幕之协程状态切换

    本文承接上一篇文章[golang内幕之程序启动流程][https://blog.csdn.net/QQ1130141391/article/details/96197570] 在 [golang内幕之 ...

  7. 基于Python3多进程(多线程)+多协程的数据并发处理模版

    图片来源:elenabsl/Shutterstock 上一篇文章<基于Python3单进程+多线程+多协程的生产者-消费者模型示例代码>介绍了如何使用Python在单进程的情况下利用协程并 ...

  8. golang 单协程和多协程的性能测试

    测试数据:单协程操作1亿数据,以及多协程(10条协程)操作1亿数据(每条协程操作1kw数据) 废话少说,贴代码: 单协程测试运算: package mainimport ("fmt" ...

  9. Golang并发模型:轻松入门协程池

    goroutine是非常轻量的,不会暂用太多资源,基本上有多少任务,我们可以开多少goroutine去处理.但有时候,我们还是想控制一下. 比如,我们有A.B两类工作,不想把太多资源花费在B类务上,而 ...

最新文章

  1. 视觉Transformer最新综述
  2. 斯坦德机器人收购_斯坦德机器人合伙人兼CMO王茂林:人是公司发展根本,多数企业都死于合伙人...
  3. day3 python 函数
  4. html格式文档结构保存数据库6,freeCAD文档结构
  5. [转]常用数字处理算法的Verilog实现
  6. SAP Business Application Studio和SAP云平台Destination
  7. [RabbitMQ]消息应答概念_消息手动应答代码
  8. HttpClient官方sample代码的深入分析(连接池)
  9. 遇到这 4 个迹象,赶紧下来、让人工智能上!
  10. bzoj 1878: [SDOI2009]HH的项链 ——树状数组+ 差分
  11. 智慧食堂管理系统打造健康食堂新理念
  12. 神经网络自我进化模型,神经网络自我进化方向
  13. Cisco 安全设备管理工具:SDM
  14. 简单的限流保护电路图大全(六款简单的限流保护电路设计原理图详解)
  15. java抓取豆瓣网页内容_爬虫实践--豆瓣电影当前上映电影信息爬取
  16. 如何获取android手机mac地址,Android手机如何获取Mac地址
  17. 本科课程【虚拟现实引擎Unity3D】实验3 - 烘焙光影贴图与动画应用
  18. Windows上帝模式——隐私浏览必备
  19. LeetCode05最长回文子串
  20. 近况记录丨脑子错乱!

热门文章

  1. 保护导师,从我做起;爱护博导,人人有责
  2. 吃了一辈子大米,你还在相信水稻种水里是因为喜欢水?
  3. Randomatic mac - AE随机摆动的字母图层效果脚本
  4. 中国电子学会python等级考试一级
  5. 白鹭引擎制作滚动框,类似div的oveflow
  6. RTX5 | 内存池04 - 共享内存用于线程之间的通讯(阻塞方式)- 使用信号量
  7. python遍历集合_Python 高效遍历 集合所有子集的全组合
  8. 购书中心管理系统的设计
  9. Linux笔记-centos7替换yum及编译安装mydumper
  10. WEB安全基础-点击劫持漏洞基础