select 数据结构

诺唯 · · 1266 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

select case 最终会被编译器,编译成

select {
    case v, ok = <-c:
        ... foo
    default:
        ... bar
}

    as

if c != nil && selectnbrecv2(&v, &ok, c) {            
        ... foo
    } else {
        ... bar
}   
select {
    case v = <-c:
        ... foo
    default:
        ... bar
}

    as

if selectnbrecv(&v, c) {
        ... foo
    } else {
        ... bar
}
select {
    case c <- v:
        ... foo
    default:
        ... bar
    }
   as
if selectnbsend(c, v) {
        ... foo
    } else {
        ... bar
}

我们在使用select 有以上三种情况,编译器会做对应的转化,上面的这三个selectnbsend、selectnbrecv、selectnbrecv2 函数最终都分别调用runtime.chansend、runtime.chanrecv 对于channel的操作 select是不可缺少的一部分,但是需要注意的是,select并不像switch那样case顺序执行的,例如下面的代码: “因为select 的case 是伪随机的,所以才会引发异常”。

func main() {
	runtime.GOMAXPROCS(1)
	int_chan := make(chan int, 1)
	string_chan := make(chan string, 1)
	int_chan <- 1
	string_chan <- "Golang我们走,我们要做好朋友!!!"
	for {
		select {
		case value := <-int_chan:
			fmt.Println(value)
		case value := <-string_chan:
			panic(value) //总会随机到我,我会执行的。。。
		}
	}
}

这里需要注意下虽然case被随机了,但是所有case关键字右侧的发送或者接受语句中的表达式和元素表达式都要被先求值,求值的顺序分别是自上而下,从左到右的顺序。

在源码中每一个select 对应一个hselect结构 每个hselect 结构下面都有个scase的数组记录每个case, 在scase中记录着c hchan的结构也就是专栏的上一篇文章channel的结构 pollorder 将元素从新排列,scase就被乱序了。

func main() {
	runtime.GOMAXPROCS(1)
	int_chan := make(chan int, 1)

	select {
	default:
		fmt.Println("default...")
	case value := <-int_chan:
		fmt.Println(value)
	}
}

最后还要说明一下,select里面的default 和case的位置摆放顺序,不会影响分支选择的规则。


有疑问加站长微信联系(非本文作者)

本文来自:知乎专栏

感谢作者:诺唯

查看原文:select 数据结构

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1266 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传