golang channel 的使用
本文对channel使用中的几个疑惑,以例子的形式加以说明。
普通channel
缺省情况下,发送和接收会一直阻塞着,直到另一方准备好.
例如:
package main
import (
"fmt"
"time"
)
var ch1 chan bool
func main(){
ch1 = make(chan bool)
go reader()
go writer()
select {
}
}
func writer() {
time.Sleep(10*time.Second)
for {
ch1 <- true
fmt.Println("write one ...")
}
}
func reader() {
for {
select {
case <-ch1:
fmt.Println("read one ....")
}
time.Sleep(2*time.Second)
}
}
output:
$ ./chan1.exe
write one …
read one ….
read one ….
write one …
read one ….
write one …
read one ….
write one …
从执行结果看,reader卡住,直到writer sleep后就位,才继续执行。反之,让reader先睡眠,writer也会卡住,直到reader sleep后就位。
带buffer的channel
带buffer的channel可以减少阻塞,对一些需要只保持有限个执行过程的情景很有用。
例1:
// reader wait, until writer begin to write.
package main
import (
"fmt"
"time"
)
var ch1 chan bool
func main(){
ch1 = make(chan bool, 1)
go reader()
go writer()
select {
}
}
func writer() {
time.Sleep(10*time.Second)
for {
ch1 <- true
fmt.Println("write one ...")
}
}
func reader() {
for {
select {
case <-ch1:
fmt.Println("read one ....")
}
time.Sleep(2*time.Second)
}
}
这种情景中,先让writer睡眠,reader此时卡住,直到writer就位,也就是说,带buffer,如果没有数据写入,reader也是卡住的。
例2:
// writer write one, then wait
package main
import (
"fmt"
"time"
)
var ch1 chan bool
func main(){
ch1 = make(chan bool, 1)
go reader()
go writer()
select {
}
}
func writer() {
for {
ch1 <- true
fmt.Println("write one ...")
}
}
func reader() {
time.Sleep(10*time.Second)
for {
select {
case <-ch1:
fmt.Println("read one ....")
}
time.Sleep(2*time.Second)
}
}
如果先让reader睡眠,writer直接向channel写,可以看到writer可以写入一个数据,然后卡住,直到reader就位,才可以继续写。
也就是说,带一个buffer的channel,可以在reader就位前首先写入一个数据。
关闭channel
可以使用內建close关闭channel,例如,
close(ch)
当channel关闭后,继续写入会报:
panic: send on closed channel
- 如果从这个关闭的channel中读数据,不但可以读取出已发送的数据,还可以不断的读取零值。
如何判断channel已经关闭了?
通过range读取
channel关闭后for循环会跳出:for v := range chan {
…
}通过i, ok := <-c
可以查看Channel的状态,判断值是零值还是正常读取的值。
如果ok是false,表示没有数据可读,并且channel已经关闭。
建议
- 只有发送者去关闭channel,接收者不要去关闭channel。
如果channel已经关闭,发送者会引起panic。 - 通常情况下,没有必要关闭channel。
参考
http://colobu.com/2016/04/14/Golang-Channels/
还没有评论,来说两句吧...