channel的使用场景,经常是不同协程之间的通信,一个协程写数据,另外的一个协程读取数据。这个时候就需要协程之间的广播机制。
原始代码:
func dataProduce(ch chan int, wg *sync.WaitGroup) {
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
wg.Done()
}()
}
func dataConsume(ch chan int, wg *sync.WaitGroup) {
go func() {
for i := 0; i < 10; i++ {
data := <-ch
fmt.Printf("输出data=%d \n", data)
}
wg.Done()
}()
}
func TestChannel(t *testing.T) {
var wg sync.WaitGroup
ch1 := make(chan int)
wg.Add(1)
dataProduce(ch1, &wg)
wg.Add(1)
dataConsume(ch1, &wg)
wg.Wait()
}
执行TestChannel的函数,代码会输出
=== RUN TestChannel
输出data=0
输出data=1
输出data=2
输出data=3
输出data=4
输出data=5
输出data=6
输出data=7
输出data=8
输出data=9
--- PASS: TestChannel (0.00s)
PASS
这个时候是事先约定了数据的个数,其实可以通过广播的形式,拿到写协程的状态,自动做处理。
在读取channel的时候,会有两个返回值
data, ok := <-ch
data: 在channel读取的数据
ok: 如果为true,表示写数据的channel没有关闭;false表示写数据的channel已经关闭
优化一下逻辑
func TestChannel(t *testing.T) {
var wg sync.WaitGroup
ch1 := make(chan int)
wg.Add(1)
dataProduce2(ch1, &wg)
wg.Add(1)
dataConsume2(ch1, &wg)
wg.Wait()
}
func dataProduce2(ch chan int, wg *sync.WaitGroup) {
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
wg.Done()
}()
}
func dataConsume2(ch chan int, wg *sync.WaitGroup) {
go func() {
for true {
if data, ok := <-ch; ok {
fmt.Printf("输出data=%d \n", data)
} else {
fmt.Println("produce channel has closed.")
break
}
}
wg.Done()
}()
}
输出结果
=== RUN TestChannel
输出data=0
输出data=1
输出data=2
输出data=3
输出data=4
输出data=5
输出data=6
输出data=7
输出data=8
输出data=9
produce channel has closed.
--- PASS: TestChannel (0.00s)
PASS