-
博文分类专栏
- Jquery基础教程
-
- 文章:(15)篇
- 阅读:46569
- shell命令
-
- 文章:(42)篇
- 阅读:154246
- Git教程
-
- 文章:(36)篇
- 阅读:234885
- leetCode刷题
-
- 文章:(76)篇
- 阅读:131875
-
go语言中通道channel详解2018-04-17 10:55 阅读(4498) 评论(0)
一、go语言中通道是什么
一旦涉及到并行,往往不开避免要处理共享数据的读写问题。当有多个goroutine在执行,如下:
func main() { var i int = 32 go func(arg int) { fmt.Println(arg) }(i) }
上面程序会输出什么呢?
答案:什么都没有。
因为:主线程执行完后就结束了,子线程会随着主线程的结束而结束。
为了让上面的子线程有时间执行,我们可以在程序中添加等待时间,如下:
time.Sleep(time.Second)
当子线程比较多或少比较耗时的时候,我们应该添加多长的等待时间才能确保子线程都能完全执行呢?
试想,若子线程执行完成后,能够通知主线程去结束,是不是就能够解决问题了。怎么通知呢?这就可以利用通道来实现了。
我们可以把通道想象成管道(类比shell中的管道,当然go里面的通道不仅仅是shell管道那么单一),负责数据的传输。
这样,我们将上面程序,改为如下,就可以正常输出了:
func main() { var i int = 32 chanFlag := make(chan int) go func(arg int) { fmt.Println(arg) chanFlag <- arg // 忘管道里面写数据,通知主线程可以结束了 }(i) <- chanFlag fmt.Println("可以结束了") }
二、go语言中通道的特点
看到上面的案例,可能会让人不解,为什么添加了<- chanFlag,就会让主线程必须等待子线程完成后才能结束呢?这就要知道通道的特点。
go语言中,依据是否具有缓存功能,可以将通道分为有缓存和无缓冲的通道;依据读写功能,可以将通道分为,双向通道和单向通道。
1、有缓存和无缓冲的通道
(1)无缓存的通道
无缓存的通道,又被称为同步通道,指的是通道没有缓存数据,它要求发送端的发送和接受端的接受必须是同步的,如果某一端的操作没有准备好,另外一端的操作就会阻塞等待,直到准备好为止。
所以,在上面的案例中,在子线程没有把arg值写入通道chanFlag之前,<- chanFlag会造成主线程一直处于阻塞状态。
(2)有缓存的通道
有缓存的通道,缓存是一个队列,队列的最大容量,即我们make创建通道时,通过第二个参数指定的,如下:
ch := make(chan int, 5)//创建一个能够包含5个int变量的通道
对于有缓冲的通道,向其发送操作就是向队列的尾部插入元素;接收操作就是从队列的头部删除元素,并返回这个刚刚删除的元素。
当队列满的时候,发送操作会阻塞;
当队列空的时候,接受操作会阻塞。
2、双向通道和单向通道
(1)双向通道
双向通道,指的是允许读操作和写操作的通道。
(2)单向通道
单向通道,指的是只可读操作或是只可写操作的通道。要想定义一个单向通道,只需要在定义的时候,带上<- 即可,如下:
var ch1 chan<- int //只能发送 var ch2 <-chan int //只能接收
三、go语言中通道的使用
1 、通道的定义
通过make函数来定义,格式如下:
var ch [chan|chan <-|<-chan] = make(type[,size])
2、往通道里面写入数据
比如往 bool 类型的通道ch中写入数据,如下:
ch <- true
3、从通道里面读出数据
比如从ch通道里面读取数据
fmt.Println(<- ch)