Go 语言入门 1-管道的特性及实现原理

打印 上一主题 下一主题

主题 1705|帖子 1705|积分 5115

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
入坑 go 也快一年了,从今天开始会定期分享一下 Go 语言学习过程中的一些基础知识。
 
go 语言中的管道, 主要是用于协程之间的通信, 比 UNIX 的管道更加轻量和易用。
 
我们先看一下管道的数据结构:
 
  1. type hchan struct {  gcount   uint  // 环形队列剩余元素个数  dataqsiz uint // 环形队列长度  buf      unsafe.Pointer // 环形队列指针  elemsize uint16  // 每个元素大小  closed   uint32  // 标识关闭状态  elemtype *_type  // 元素类型  sendx    uint   // 下一个元素写入时的下标  recvx    uint   // 下一个元素读取时的下标  recvq    waitq  //  等待读消息的队列  sendq    waitq  // 等待写消息的队列  lock     mutex  // 互斥锁, 保障管道无法并发读写}
复制代码
源码链接:
https://github.com/golang/go/blob/0d0193409492b96881be6407ad50123e3557fdfb/src/runtime/chan.go#L33

通过上述数据结构, 我们可以理解管道是由三部分组成的:
环形队列
读写等待队列
队列元素基本信息
 
从管道读取数据时, 如果管道缓冲区为空或者没有缓冲区, 那么当前协程就会阻塞, 然后放入 recvq 队列中。
 
往管道写入数据时, 如果管道缓冲区为空或者缓冲区满了, 那么当前协程就会阻塞, 然后放入 sendq 队列中。
 
读阻塞的协程会被新来的写数据的协程唤醒。
写阻塞的协程会被新来的读数据的协程唤醒。
 
同时上述数据结构中, 我们可以看到一个管道中只能传递一种元素类型。 如果想数据类型动态化, 可以传递 interface。
 
管道的操作:
 
初始化有两种方式:
 
变量声明:
  1. var ch chan int  // 声明一个新的管道
复制代码
使用 make:
  1. ch1 := make(chan string)  // 无缓冲管道ch1 := make(chan string 3)  // 有缓冲管道
复制代码
 

管道的读写是通过操作符: 「
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曂沅仴駦

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表