go语言学习笔记(9)通道进阶

通道进阶
1.单向通道以及单向通道的作用
单向通道就是只能发不能收,或者只能收不能发的通道。示例:var uselessChan = make(chan <- int, 1)只能发不能接收通道 ,var uselessChan = make(<-chan int, 1)只能接收不能发送通道.
单向通道可以用来限制代码行为:
(1)限制函数行为
例子:
func SendInt(ch chan<- int) {
ch <- rand.Intn(1000)
}
通过限制函数的参数,使得这个函数中的代码只能向ch发送元素值,而不能接收元素值
(2)限制接口实现
例子:
type Notifier interface {
SendInt(ch chan<- int)
}
通过这种方式,对接口所有的实现做出了约束,在调用sentInt方法的时候我们只需要传入一个双向通道,因为Go语言在这种情况下会自动把双向通道转换为单向通道.
(3)限制函数的调用方
例子:
func getIntChan() <-chan int {
num := 5
ch := make(chan int, num)
for i := 0; i < num; i++ {
ch <- i
}
close(ch)
return ch
}
通过限制函数的返回结果,来限制的到该通道的函数,只能从通道中接受函数值,以此来实现对函数调用方的限制。
(4)还可以通过对在函数类型中使用单向通道,来限制所有这个函数类型的函数。

2.for range获取通道内的值
例子:
intChan2 := getIntChan()
for elem := range intChan2 {
fmt.Printf("The element in intChan2: %v\n", elem)
}
这样一条for语句会不断地从intChan2中取出元素值,即使intChan2被关闭,它也会继续取出所有剩下的元素值再结束执行。
intChan2中没有元素值时,它会阻塞再for关键字那一行。
intChan值为nil时,它会被永远阻塞再for关键字哪一行。
3.Select子句,专门为通道设计的语句
select语句只能和通道连用,由若干个分支组成一次只能执行一个符合要求的分支,每个case表达式中只能
包含操作通道的表达式。select由候选分支和默认分支组成。候选分支由case开头,默认分支由default开头。当所有候选分支没有选到的时候就会执行默认分支。
注意点:
(1)如果加入了默认分支,无论涉及到的通道操作是否阻塞,select语句都不会阻塞。
(2)如果没有默认分支,一旦所有的case没有满足条件,那么selec会被阻塞,知道有一个case满足条件。
(3)可以在接受表达式通过第二个结果值来判断通道是否关闭,一旦某个通道关闭,这时要及时屏蔽对应分支,这样能够提升程序性能。
(4)可以通过在for循环中嵌套select来连续,或者定时操作其中的通道,注意在select中使用break只会跳出当前分支。
select的分支选择规则:
  1. 对于每一个case表达式,都至少会包含一个代表发送操作的发送表达式或者一个代表接收操作的接收表达式,同时也可能会包含其他的表达式。比如,如果case表达式是包含了接收表达式的短变量声明时,那么在赋值符号左边的就可以是一个或两个表达式,不过此处的表达式的结果必须是可以被赋值的。当这样的case表达式被求值时,它包含的多个表达式总会以从左到右的顺序被求值。
  2. select语句包含的候选分支中的case表达式都会在该语句执行开始时先被求值,并且求值的顺序是依从代码编写的顺序从上到下的。结合上一条规则,在select语句开始执行时,排在最上边的候选分支中最左边的表达式会最先被求值,然后是它右边的表达式。仅当最上边的候选分支中的所有表达式都被求值完毕后,从上边数第二个候选分支中的表达式才会被求值,顺序同样是从左到右,然后是第三个候选分支、第四个候选分支,以此类推。
  3. 对于每一个case表达式,如果其中的发送表达式或者接收表达式在被求值时,相应的操作正处于阻塞状态,那么对该case表达式的求值就是不成功的。在这种情况下,我们可以说,这个case表达式所在的候选分支是不满足选择条件的。
  4. 仅当select语句中的所有case表达式都被求值完毕后,它才会开始选择候选分支。这时候,它只会挑选满足选择条件的候选分支执行。如果所有的候选分支都不满足选择条件,那么默认分支就会被执行。如果这时没有默认分支,那么select语句就会立即进入阻塞状态,直到至少有一个候选分支满足选择条件为止。一旦有一个候选分支满足选择条件,select语句(或者说它所在的 goroutine)就会被唤醒,这个候选分支就会被执行。
  5. 如果select语句发现同时有多个候选分支满足选择条件,那么它就会用一种伪随机的算法在这些分支中选择一个并执行。注意,即使select语句是在被唤醒时发现的这种情况,也会这样做。
  6. 一条select语句中只能够有一个默认分支。并且,默认分支只在无候选分支可选时才会被执行,这与它的编写位置无关。
  7. select语句的每次执行,包括case表达式求值和分支选择,都是独立的。不过,至于它的执行是否是并发安全的,就要看其中的case表达式以及分支中,是否包含并发不安全的代码了。
拓展:发现一个通道被关闭后,防止再次进入该分支,可以将该通道赋值
为长度为0的非缓冲通道。
例子:for {
select {
case _, ok := <-ch1:
if !ok {
ch1 = make(chan int)
}
case ..... :
default:
}
}


转载于:https://juejin.im/post/5ba0de6b6fb9a05d1b2e4b22

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值