本文对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后就位。
<div class="se-preview-section-delimiter"></div>
##带buffer的channel
带buffer的channel可以减少阻塞,对一些需要只保持有限个执行过程的情景很有用。
例1:
<div class="se-preview-section-delimiter"></div>
// 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:
<div class="se-preview-section-delimiter"></div>
// 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就位前首先写入一个数据。