目录

  • channel相关
    • channel基础
      • 无缓冲的channel
      • 单方向的channel
      • 有缓冲的channel
      • channel的常用操作示例
      • channel底层源码实现
    • channel面试题
      • 同一个协程里,对一个无缓冲的channel同时发送和接收数据有什么问题?有缓冲呢?
      • channel的应用场景?
      • channel和锁的对比?

channel相关

channel基础

1、channel的初始化

ch := make(chan int64, 10): 创建一个可发送int64类型数据的channel,其容量为10

  1. make() 创建出的channel是一个引用类型,当对channel进行复制和函数传递时,也只是拷贝了改channel的引用
  2. channel可以使用 == 进行比较。当两个channel引用底层数据结构是同一个时,返回true

2、channel的关闭

close(ch): 表示channel被关闭

  1. 发送。发送消息给一个已关闭的channel,会触发panic
  2. 接收。channel关闭后依然可以接收channel中的消息,当channel中无消息时,返回对应数据类型的零值
  3. 试图重复关闭一个channel会触发panic异常
  4. 试图关闭一个nil值的channel会歘panic异常

3、channel的数据统计

len(ch): channel队列中已有元素的个数
cap(ch): channel队列的容量

无缓冲的channel

当初始化channel不指定通道容量(或指定容量为0)时,该通道为无缓冲channel;

1、无缓冲channel的特性

一个无缓冲channel的发送操作将导致发送者goroutine的阻塞,直到另一个goroutine在相同的channel上执行接收操作
同理接收者阻塞,直到另一个goroutine发送

2、无缓冲channel的用途

  1. 同步操作。如事件A(goroutineA)必须在事件B(goroutineB)之前完成,则在goroutineA中完成时间A后发送无缓冲channel,goroutineB中接收到统一channel的消息再执行事件B
  2. Pipeline. 可以使用多个无缓冲channel连接多个goroutine,形成一个管道(pipeline)。

3、goroutine泄露

func testGoroutineLeak() {ch := make(chan int64)go func() { ch <- 64 }()go func() { ch <- 52 }()go func() { ch <- 41 }()<-ch
}

当无缓冲channel的发送者goroutine数量和接受者goroutine数量不一致时,会导致较多一方的goroutine阻塞,且无法自动回收(goroutine不会自动被回收),造成goroutine泄露

单方向的channel

  1. 双向channel可以隐式转换为单方向channel
  2. 反之不可

有缓冲的channel

当初始化channel时指定通道容量,该通道为有缓冲的channel;

有缓冲的通道可以一定程度上解决上述“无缓冲通道”引发的goroutine泄露问题

channel的常用操作示例

1、使用for range读channel

场景:需要轮询channel中的数据
优点:当channel关闭时自动退出循环,无需额外判断channel是否关闭;
用法:

for x := range ch {
do_something(x)
}

2、使用_, ok判断channel是否关闭

场景:读channel,但不确定channel是否关闭
优点:可以通过ok值明确判断channel是否关闭,不受channel类型本身0值的影响
用法:

if x, ok := <- chan {
do_something(x)
}

3、使用select处理多个channel

场景:

  1. 需要读取/写入多个通道时,不因一个通道的阻塞影响另一个通道的写入
  2. 需要给读取/写入操作增加超时时间

4、消息广播

场景:协程退出时,通知所有子协程退出。关闭通道close(ch)后,所有子协程可以感知通道关闭并自动退出

channel底层源码实现

传送门

channel面试题

同一个协程里,对一个无缓冲的channel同时发送和接收数据有什么问题?有缓冲呢?

同一个协程是串行的,无法同时做“发送”和“接收”两个事情,只能先发后收,或者先收后发。

  1. 无缓冲:会造成goroutine阻塞,协程对一个无缓冲的channel发送(或者接收)消息会阻塞;
  2. 有缓冲:正常执行。
    • 但是没必要?同一个协程的通信直接函数调用或者串行代码逻辑

channel的应用场景?

  1. 协程间的数据通信

    • 多个协程通过发送和读取同一个channel来实现消息传递
  2. 并发控制
    • channel可以做消息分流,增加并行消费者(kafka消费者场景)
  3. 消息队列
    • 本地的生产消费模型中,可用作消息队列
  4. 同步操作
    • 无缓冲的channel可以用作对同步操作的控制,在前执行的事件需要执行完发送channel,在后执行的事件接收到channel的消息后再执行
  5. 管道PIPELINE
    • 多个无缓冲的channel可连接多个goroutine,实现数据流管道;如:

      • goA产生数据0、1、2 给chanA
      • goB接收chanA,执行平方操作,给chanB
      • goC接收chanB, 执行两数相加操作;最终可实现0 + 1*1 + 2*2 + 3*3...这种场景
  6. 消息广播
    • channel发送特定的消息,接收者接收消息执行约定好的行为
    • 可以通过close(ch)广播事件,下游接收ch消息的协程可感知channel关闭,后执行对应操作

channel和锁的对比?

channel是线程安全的,使用channel可以解决数据并发问题;但是channel解决并发问题的场景是“数据的流动性”,数据在动,channel不动(提供了串行获取流动数据的能力)

锁mutex也可以解决并发访问资源的问题;但是mutex更多解决“静态数据”的问题,即数据不动,某段时间控制只给一个协程访问

Golang应用专题 - channel相关推荐

  1. GoLang之图解channel之读、写、关闭

    文章目录 GoLang之图解channel之读.写.关闭 GoLang之图解channel之读.写.关闭 为什么这样写就不会阻塞了呢?因为下面的代码会被编译器转换为对runtime.selectnbs ...

  2. golang已关闭channel

    golang 向已关闭的 channel 发送数据会造成 panic package mainimport ("fmt""time" )func main() ...

  3. 手把手教姐姐写消息队列(golang)- 使用channel实现消息队列

    前言 这周姐姐入职了新公司,老板想探探他的底,看了一眼他的简历,呦呵,精通kafka,这小姑娘有两下子,既然这样,那你写一个消息队列吧.因为要用go语言写,这可给姐姐愁坏了.赶紧来求助我,我这么坚贞不 ...

  4. Golang并发模式--channel高级使用

    or-done channel 再pipeline的情况中,我们通过done来通知goroutine结束.但是,如果我们处理的channel来自系统其它分散的部分,则无法通过done来控制,因为我们不 ...

  5. [Golang数据库专题4]Golang语言操作PostgreSQL进行增删改查

    目录 一. 引言 1.1 PostgreSQL与MYSQL 1.2 Golang支持PostgreSQl驱动 二.编码实践 2.1 建表语句 2.2 CRUD代码 2.3 验证结果 三.结语 一. 引 ...

  6. [Golang数据库专题3]Golang语言操作SQLite3进行增删改查

    目录 一.SQLite3安装(linux) 1.2 在线安装 开始安装 目录下创建db 执行表创建语句 二.方案选型 三.编写代码 3.1 代码运行环境准备 Go语言环境 SQLite3生成db 3. ...

  7. golang入门笔记—channel

    //channel//var b chan <类型> //通道必须用make函数初始化才能使用//通道的操作 //1.发送:ch1<-1 //2.接收:x:=<-ch1 //3 ...

  8. [Golang数据库专题1]datbase/sql接口

    目录 一 .引言 1.1 概述 1.2 包接口 二.database/sql接口(常用) 1.sql.Register 2.driver.Driver 3. driver.Conn 4. driver ...

  9. golang中并发sync和channel

    golang中并发sync和channel chenbaoke · 2014-12-08 13:00:01 · 19151 次点击 · 预计阅读时间 5 分钟 · 不到1分钟之前 开始浏览 这是一个创 ...

最新文章

  1. jwt token 附加用户信息_SpringBoot+JWT实现token验证并将用户信息存储到@注解内
  2. 二进制日志和数据更新的关系
  3. IDEA中查看SVN项目历史版本更新信息
  4. 【数据结构基础应用】【顺序表】
  5. 如何进入embl的ebi网站fasta3服务器,The EMBL-EBI bioinformatics web and programmatic tools framework...
  6. 【Elasticsearch】 Elasticsearch slop管理间隔字符查数据
  7. ITIL与DevOps
  8. Linux沙箱技术简介
  9. HDU 6975 Forgiving Matching 快速傅里叶变换处理带通配符字符串匹配
  10. 数据密集型系统设计:索引及存储(B树、LSM树、OLTP及OLAP)
  11. 09-kafka分区数的设置
  12. android中奖名单轮播,iOS模拟中奖名单循环滚动效果
  13. Web测试的各个测试点
  14. 解决json数据 key为数字,自动排序问题
  15. 瞎折腾实录:构建 Armel 版本的 .NET Core 教程和资料资源
  16. python批量打印mathcad_转载:简单比较几个计算数学软件 Matlab Mathematica MathCAD
  17. 来自一位十余年工作经验的老电子工程师的心里话:该出手时便出手!
  18. r720支持多少频率的内存吗_2020年十一月电脑内存选购指南,如果选择性价比内存条(内存天梯)...
  19. 在正确的时间吃正确的水果
  20. Pexpect模块使用

热门文章

  1. 李嘉诚撤资连环计:等待中国危机 欧洲只是跳板
  2. Thymeleaf th:include、th:replace使用
  3. 4D毫米波雷达:成像距离超百米,成本仅为LiDAR十分之一
  4. 2018中国高校计算机大赛—大数据挑战赛(top2解题方案)
  5. 开源的AI算法可以进行物体识别,动物识别
  6. 逆向分析入门实战(三)
  7. 不同分辨率加载不同js_OpenLayers加载百度离线瓦片地图(完美无偏移)
  8. TCP/UDP协议抓包-工具wireshark与tcp侦听工具
  9. mysql 数据导入sqlserver_MySQL数据库导入SqlServer实践经验总结
  10. AutoHotkey实现赛尔号自动换背包精灵