Go 语言源码分析——channel

本文详细分析了Go语言中channel的实现,包括数据结构、创建、发送数据、接收数据和关闭channel的操作。通过channel,Go实现了并发编程中的通信共享内存模型,避免了线程之间的锁竞争。在操作channel时,需要注意非阻塞操作、未初始化和关闭channel的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Go 语言最常提及的设计模式就是:不要通过共享内存的方式进行通信,而是应该通过通信的方式共享内存。许多主流编程语言中,多个线程传递数据的方式是共享内存,其中会涉及到线程之间竞争锁的问题。在Go中也提供了共享内存加互斥锁进行通信的方式,但Go还提供了一种不同的并发模型,即通信顺序进程(Communicating sequential processes,CSP),其中goroutine和channel分别对应CSP模型中的实体和传递数据的媒介。在Go中,goroutine可通过channel进行通信。

一、数据结构

type hchan struct {
	qcount   uint           // 缓冲区中数据的数量
	dataqsiz uint           // 缓冲区的大小
	buf      unsafe.Pointer // 指向缓冲区的指针
	elemsize uint16         // 元素的大小
	closed   uint32         // channel是否关闭
	elemtype *_type         // e元素类型
	sendx    uint           // 发送操作处理到的位置
	recvx    uint           // 接收操作处理到的位置
	recvq    waitq          // 接收队列
	sendq    waitq          // 发送队列
	lock mutex              // 互斥锁
}

 二、操作

1.创建channel

创建channel最终是通过makechan方法操作的,输入为要创建的channel的类型和大小,并返回一个hchan的指针

func makechan(t *chantype, size int) *hchan

首先对要创建的channel进行检查,如元素大小是否合法、要创建的channel大小是否合法等

elem := t.elem

if elem.size >= 1<<16 {
	throw("makechan: invalid channel element type")
}
if hchanSize%maxAlign != 0 || elem.align > maxAlign {
	throw("makechan: bad alignment")
}

mem, overflow := math.MulUintptr(elem.size, uintptr(size))
if overflow || mem > maxAlloc-hchanSize || size < 0 {
	panic(plainError("makechan: size out of range"))
}

接着为channel分配内存并初始化hchan的其他参数

var c *hchan
switch {
case mem == 0:
	c = (*hchan)(mallocgc(hchanSize, nil, true))
	c.buf = c.raceaddr()
case elem.ptrdata == 0:
	c = (*hchan)(mallocgc(hchanSize+mem, nil, true))
	c.buf = add(unsafe.Pointer(c), hchanSize)
default:
	c = new(hchan)
	c.buf = mallocgc(mem, elem, true)
}

c.elemsize = uint16(elem.size)
c.elemtype = elem
c.dataqsiz = uint(size)

然后channel创建成功并返回

2.发送数据

当通过c <- x 发送数据时,最后会调用到chansend方法,该方法接受一个channel的指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值