本文对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就位前首先写入一个数据。