Go channel 关闭和广播
代码语言:javascript复制Dont Communicate by sharing memory, sharing memory by communicate.
不要通过共享内存的方式通讯,要通过通讯的方式共享内存
Channel 基本概念
一个通道相当于 FIFO 的队列, 通道中各个元素之间都是严格按照发送的顺序队列,先发送的队列一定会被先接收,元素值的发送和传输和发送都使用到操作符 <-
channel 的关闭
- 向关闭的 channel 发送数据, 会导致 panic
package main
import (
"fmt"
"sync"
"testing"
)
func dataProducer(ch chan int, wg *sync.WaitGroup) {
go func() {
for i := 0; i < 11; i {
ch <- i
}
wg.Done()
}()
}
func dataConsumer(ch chan int , wg *sync.WaitGroup) {
go func () {
for i := 0; i < 10; i {
data := <- ch
fmt.Println(data)
}
close(ch)
wg.Done()
}()
}
func TestCloseChanner(t *testing.T) {
var wg sync.WaitGroup
ch := make(chan int)
wg.Add(1)
dataProducer(ch, &wg)
wg.Add(1)
dataConsumer(ch, &wg)
wg.Wait()
}
运行结果
代码语言:javascript复制GOROOT=C:Go #gosetup
GOPATH=D:GoWorkSpace #gosetup
C:Gobingo.exe test -c -o C:UserswangmAppDataLocalTemp___channel_close_test_go.exe GoProject/src/main/gobase/channel #gosetup
C:Gobingo.exe tool test2json -t C:UserswangmAppDataLocalTemp___channel_close_test_go.exe -test.v -test.run ^QTestCloseChannerE$ #gosetup
=== RUN TestCloseChanner
0
1
2
3
4
5
6
7
8
9
panic: send on closed channel
goroutine 20 [running]:
GoProject/src/main/gobase/channel.dataProducer.func1(0xc0000862a0, 0xc0000942b0)
D:/GoWorkspaces/GoProject/src/main/gobase/channel/channel_close_test.go:12 0x4a
created by GoProject/src/main/gobase/channel.dataProducer
D:/GoWorkspaces/GoProject/src/main/gobase/channel/channel_close_test.go:10 0x50
Process finished with exit code 1
- v, ok <- ch; ok 为 bool 值, true 表示正常接收,false 表示通道关闭
- 所有的 channel 接收者都会在 channel 关闭时,立刻从阻塞等待中返回且上述 ok 值 为 false 。这个广播机制被利用,进行多个订阅同时发送信号。
package main
import (
"fmt"
"sync"
"testing"
)
func dataProducer(ch chan int, wg *sync.WaitGroup) {
go func() {
for i := 0; i < 10; i {
ch <- i
}
close(ch)
wg.Done()
}()
}
func dataConsumer(ch chan int , wg *sync.WaitGroup) {
go func () {
for i := 0; i < 10; i {
if data, ok := <- ch; ok {
fmt.Println(data)
} else {
break
}
}
wg.Done()
}()
}
func TestCloseChanner(t *testing.T) {
var wg sync.WaitGroup
ch := make(chan int)
wg.Add(1)
dataProducer(ch, &wg)
wg.Add(1)
dataConsumer(ch, &wg)
wg.Wait()
}
运行结果
代码语言:javascript复制GOROOT=C:Go #gosetup
GOPATH=D:GoWorkSpace #gosetup
C:Gobingo.exe test -c -o C:UserswangmAppDataLocalTemp___channel_close_test_go.exe GoProject/src/main/gobase/channel #gosetup
C:Gobingo.exe tool test2json -t C:UserswangmAppDataLocalTemp___channel_close_test_go.exe -test.v -test.run ^QTestCloseChannerE$ #gosetup
=== RUN TestCloseChanner
0
1
2
3
4
5
6
7
8
9
--- PASS: TestCloseChanner (0.00s)
PASS
Process finished with exit code 0
测试代码
代码语言:javascript复制package main
import (
"fmt"
"sync"
"testing"
)
func dataProducer(ch chan int, wg *sync.WaitGroup) {
go func() {
for i := 0; i < 10; i {
ch <- i
}
close(ch)
wg.Done()
}()
}
func dataConsumer(ch chan int , wg *sync.WaitGroup) {
go func () {
for i := 0; i < 11; i {
data := <- ch
fmt.Println(data)
}
wg.Done()
}()
}
func TestCloseChanner(t *testing.T) {
var wg sync.WaitGroup
ch := make(chan int)
wg.Add(1)
dataProducer(ch, &wg)
wg.Add(1)
dataConsumer(ch, &wg)
wg.Wait()
}
运行结果:
代码语言:javascript复制GOPATH=D:GoWorkSpace #gosetup
C:Gobingo.exe test -c -o C:UserswangmAppDataLocalTemp___channel_close_test_go.exe GoProject/src/main/gobase/channel #gosetup
C:Gobingo.exe tool test2json -t C:UserswangmAppDataLocalTemp___channel_close_test_go.exe -test.v -test.run ^QTestCloseChannerE$ #gosetup
=== RUN TestCloseChanner
0
1
2
3
4
5
6
7
8
9
0
--- PASS: TestCloseChanner (0.00s)
PASS
Process finished with exit code 0