golang select

发布时间 2023-11-22 21:31:48作者: _小孟同学

golang select是多 channel 并行的利器

不要拿 switch 和 select 比,根本不是一个东西好嘛,差不少,只是名字稍微有点像

前置操作

golang 对 select 做了一些优化

select 结构体为空

当 select 里面为空的时候会直接 panic

只有一个 case

当只有一个 case 时候(包括只有一个 case 时候),会将 select 去掉

select{
case c <- x:
	return
}

转变成

c <- x
return

当有单一 case 加 default

当只有一个 case 和一个 default 时候,会转变成非阻塞的 if 操作

select{
case c <- x:
	print("ok")
default:
	print("default")
}

转变成

if (chansend()/chanrecv()){ // 非阻塞的 chansend 或 chanrecv 操作,有个 block 参数代表阻塞在通道那篇的源码有
	print("ok")
}else{
	print("default")
}

流程

当有两个以上的 case 时候,也就是普通的时候,会执行下面流程

  1. 先把所有的 channel 打乱,放入到lockorder中
  2. 然后把 lockerorder 中的 channel 都加锁
  3. 然后查看 pollorder 中是否有就绪的 channel,如果有的话就执行 send/recv 操作,将所有的其他channel 解锁
  4. 如果没有,就把当前协程加入所有对应发送/接受channel 的等待队列,然后将自己挂起(其实这个操作和一个普通goroutine 一样,都是将自己放到 channel 等待队列),然后解锁(源码没看到解锁)
  5. 等某一个 channel 可以进行写入/接受,然后加锁,找到对应的 channel ,就执行对应操作,然后解锁,或有 close 的channel也会退出

参考

由浅入深聊聊Golang中select的实现机制
golang select底层原理
深入golang -- select
图解Go中select语句的底层原理