上篇介绍了Channel是什么以及它的类型,这篇总结一下Channel的用法。
- 基本语法
(1) 声明channel
声明channel的语法格式为:
var ChannelName chan ElementType
与其他变量声明不同的是,在类型前面多了一个chan关键字。ElementType指的是这个channel能够传递的数据类型。
在golang中需要使用内置的make函数类创建channel的实例:
ch := make(chan int) //声明并初始化了一个名为ch的int型channel
(2) 发送接收数据
ch -< value //向channel中发送数据
【send操作注意】:
a) c -< 3+4 //先求值再传递
b) 往一个已经被close掉的channel中发送数据会导致run-time panic
c) 注意channel是否有缓存。无缓存的channel只有在receiver准备好后send才能被执行。有缓存且缓存未满,send可以直接被执行。
value := <- ch //将channel中的数据读取到变量中
【receive操作注意】:
a) 从一个被close的channel中取数据不会被阻塞,而是立即返回,接收完已发送的数据会返回元素类型的零值。可以用一个额外的返回参数来检查channel是否关闭:
x, ok := <-ch
x, ok = <-ch
var x, ok = <-ch
如果ok是false,表示接收的x是产生的零值,这个channel被关闭了或者为空。
(3) Select
在linux系统中,select函数用来监控一系列的文件句柄,一旦有文件句柄发生了I/O动作,select函数就会返回,主要被用来实现高并发的socket服务器程序。
Golang中,select关键字和linux的select函数功能相似,主要用于处理I/O异步问题。
select的语法与switch相似,由select开始一个新的选择块,每个选择条件由case语句来描述。
与switch语句相比,select有比较多的限制,其中最大的一条限制就是每个case语句必须是一个I/O操作。
大致结构:
select {
case <-chan1: //如果 chan1 成功读取到数据,则执行该 case
case chan2 <- 1://如果成功向 chan2 写入数据,则执行该 case
default: // 如果上面的条件都没有成功,则执行 default 流程
}
可以看出,select 不像 switch,后面并没有条件判断,而是直接去查看 case 语句。每个 case 语句都必须是一个面向 channel 的操作。
- channel的遍历
for …… range
语句可以遍历channel。但是它会一直迭代直至channel被关闭。
图中例子,如果把close(c)注释掉,程序会一直阻塞在for…range那行。
再看一个例子:
这段代码可以正常执行。
换成这段代码,会出现fatal error: all goroutines are asleep - deadlock!
总之,for…range是阻塞式读取channel,只有channel close后才会结束。
- 处理超时
在使用channel的时候要小心,比如
i := <= ch
当碰到永远没有往ch中写入数据的情况,那么这个读取就永远无法成功。导致的结果就是整个goroutine永远阻塞并且没有挽回的机会。
Golang没有提供直接的超时处理机制。可以利用select机制来解决,因为select的特点是只要其中一个case满足,程序就会继续往下执行,而不会考虑其他的case。基于此特性,可以实现一个channel的超时机制:
ch := make(chan int)
//
首先实现并执行一个匿名的超时等待函数
timeout := make(chan bool, 1)
go func() {
time.Sleep(1e9) //
等待
1
秒
timeout <- true
}()
//
然后把
timeout
这个
channel
利用起来
select {
case <-ch:
//
从
ch
中读取到数据
case <- timeout:
//
一直没有从
ch
中读取到数据,但从
timeout
中读取到了数据
fmt.Println("Timeout occurred.")
}
执行上述代码,输出结果为:
Timeout occurred.
- 关闭channel
内建的close方法可以用来关闭channel:
close(ch)
判断一个channel是否已关闭,可以增加一个布尔类型的值:
x, ok := <-ch
如果ok的值为false,就表示已经被关闭。
标签:case,ch,ok,Golang,Channel,channel,close,select From: https://www.cnblogs.com/gongxianjin/p/17535125.html