Go 的分支语句 “ select ”
我请想请教一下,我该如何通俗的理解这个语句的实际作用和运行原理,官方的说明如下:
“ select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个通信操作,要么是发送要么是接收。 select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。
1.每个 case 都必须是一个通信 2.所有 channel 表达式都会被求值 3.所有被发送的表达式都会被求值 4.如果任意某个通信可以进行,它就执行;其他被忽略。 5.如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。 ”
我自己不能完全的理解的是 “每个 case 都必须是一个通信”
我的疑问如下:
1.以上文中“通信”的定义是什么?也就是在 case 中可以放什么?表达式?还是什么?
2.selcet 分支中 case 是如何进行判断的?
1
sulinehk 2019-08-08 16:43:05 +08:00 via Android
通信说的是 可以向一个通道取值或发送值
case 就是选择一个执行 |
2
poplar50 2019-08-08 16:48:11 +08:00 via Android 2
通俗讲 select 看字面意思就是选择,它会在它的 case 里选择一个来执行,那么问题来了,选择条件是什么? 其实就是哪个 case 准备好了(not blocked)就执行哪个,如果都准备好了就随机选择一个。
|
3
SuperMild 2019-08-08 16:50:38 +08:00 1
tour.golang.org 里面的例子你看看,那些例子很好。
|
4
zdt3476 2019-08-08 16:51:53 +08:00 1
1. 每个 Case 放的都是 channel; 只能放 channel; channel 发送或者是接受语句
2. 就像 你上面第 5 点说的 随机选择一个 case 来执行,比如: select { case data := <- ch1: // 可能执行这个 ... case ch2 <- data2: // 也可能执行这个 } |
5
kidlj 2019-08-08 17:08:00 +08:00
读英文。
|
6
sirgod 2019-08-08 17:28:57 +08:00
看几个实际的例子就明白了
|
7
www6688w OP @zdt3476 我现在就是没有完全明白 select 中的 case 要满足什么情况,才算是“可以运行的 case ”。
|
8
CRVV 2019-08-08 17:40:00 +08:00 1
https://golang.org/ref/spec#Channel_types
The capacity, in number of elements, sets the size of the buffer in the channel. If the capacity is zero or absent, the channel is unbuffered and communication succeeds only when both a sender and receiver are ready. Otherwise, the channel is buffered and communication succeeds without blocking if the buffer is not full (sends) or not empty (receives). A nil channel is never ready for communication. communication succeeds 就是 case 可以运行 |
9
gamexg 2019-08-08 17:44:51 +08:00 via Android 1
通信是指的 chan,
表达式最终的返回值必须是 chan。 当然还有个 default。 |
10
shingle 2019-08-08 17:45:20 +08:00 1
一个最常见的例子: 执行一个任务,最多五秒超时, 满足哪个就会触发 select 进行后续的处理
select { case result := <- ch: // 正常执行,并在 channel 里返回结果 case <- timeout: // 执行超时 } 还有一种, 用于单独开一个协程处理返回结果. for{ select result := <-ch: //do something } |
11
shingle 2019-08-08 17:49:20 +08:00 1
你给出的是机翻译文吧, 通信一词不应该被翻译...指的是 golang 内置类型 channel
|
13
yangkghjh 2019-08-08 17:58:03 +08:00
类似抢答
|
14
SmartKeyerror 2019-08-08 18:15:11 +08:00 via Android 1
不知道是哪里的翻译,但是我觉得用"通道"这个词会更好一些。channel 是通道,目的在于 goroutine 之间的通信。go select 和 Linux select 在语义层面比较相似,都是用于选取已就绪的状态,如果想对 go select 有更深的理解的话,可以看看 Linux select。
|
15
panda1001 2019-08-08 18:21:22 +08:00 via Android
同意楼上,建议参考 linux select 的原理和使用
|
16
OakScript 2019-08-08 18:50:27 +08:00 1
实在不理解就想成是用于 channel 的 switch,虽然不准确
|
17
Pythondr 2019-08-08 19:35:28 +08:00 via Android 1
都放 chan, 哪个 chan 先取到值就执行哪个 case
|
18
Y4ssss 2019-08-08 20:02:01 +08:00 1
哪个通道是没有阻塞的就选择哪个,都没阻塞随机选一个,都阻塞 select 自身阻塞
|
19
justfly 2019-08-08 21:35:51 +08:00 1
你如果了解 linux 内核网络部提供的 select epoll 之类的,理解这个就不难了。
|
20
laodao1990 2019-08-09 10:01:40 +08:00 1
为什么不静下心来了找本书系统的学习下?
推荐 《 Go 语言程序设计》 |
21
www6688w OP @laodao1990 多谢指点,不过我个人学习习惯先看一些视频教程,简单入门之后再啃书。你说的是这一本吗? https://book.douban.com/subject/27044219/
|
22
laodao1990 2019-08-15 16:24:01 +08:00
@www6688w 是的。这个是官方翻译的,github 上还有一个是网友自己翻译的
|