赞
踩
谈及channel 就不得不说并发 并行了
并发:同一时间段内执行多个任务。
并行:同一时刻执行多个任务
goroutine
类似于线程,属于用户态的线程。goroutine
是由Go语言的运行时(runtime)调度完成,而线程是由操作系统调度完成。
Go语言还提供channel
在多个goroutine
间进行通信
goroutine的调度模型:GMP
M:N:把M个goroutine分配给n个操作系统线程去执行
goroutine是用户态线程,比内核态的线程更轻量级一点,初始栈的大小是2k
可以轻松开启数十万的goroutine也不会崩内存
- var wg sync.Waitgroup
- wg.Add(xx)
- wg.Done()
- wg.Wait()
channel
是一种类型,一种引用类型
- var 变量 chan 元素类型
- var ch chan int
- fmt.Println(ch) // <nil>
-
- make(chan 元素类型, [缓冲大小])
通道有发送(send)、接收(receive)和关闭(close)三种操作。
- ch := make(chan int)
- //发送
- ch <- 10 // 把10发送到ch中
- //接收
- x := <- ch // 从ch中接收值并赋值给变量x
- <-ch // 从ch中接收值,忽略结果
- //关闭
- close(ch)
通道关闭后还是可以取值的
- ch := make(chan int, 2) // 创建一个容量为1的有缓冲区通道
- ch <- 10
- ch <- 20
- close(ch)
- for x range ch{
-
- }
- <- ch
- <- ch
- x,ok := <- ch //不会报错
单向 通道
<-chan int
是一个只读>单向通道
chan<- int
是一个只写>单向通道
在函数传参及任何赋值操作中可以将双向通道转换为单向通道,但反过来是不可以的
- select{
- case <-ch1:
- ...
- case data := <-ch2:
- ...
- case ch3<-data:
- ...
- default:
- 默认操作
- }
它有一系列case分支和一个默认的分支
每个case会对应一个通道的通信(接收或发送)过程
select
会一直等待,直到某个case
的通信操作完成时,就会执行case
分支对应的语句
可处理一个或多个channel的发送/接收操作。
如果多个case
同时满足,select
会随机选择一个。
对于没有case
的select{}
会一直等待,可用于阻塞main函数
1:关闭一个未初始化的 channel 会产生 panic
2:重复关闭同一个 channel 会产生 panic
3:向一个已关闭的 channel 发送消息会产生 panic
4:从已关闭的 channel 读取消息不会产生 panic,且能读出 channel 中还未被读取的消息,若消息均已被读取,则会读取到该类型的零值。
5:从已关闭的 channel 读取消息永远不会阻塞,并且会返回一个为 false 的值,用以判断该 channel 是否已关闭(x,ok := <- ch) :
6:关闭 channel 会产生一个广播机制,所有向 channel 读取消息的 goroutine 都会收到消息
7:channel 在 Golang 中是一等公民,它是线程安全的,面对并发问题,应首先想到 channel
8: 给一个 nil channel 发送数据,造成永远阻塞
从一个 nil channel 接收数据,造成永远阻塞
给一个已经关闭的 channel 发送数据,引起 panic
从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回一个零值
无缓冲的channel是同步的,而有缓冲的channel是非同步的
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。