朋友问了一道使用通道来实现“多线程”通讯的golang题,我看了下,还比较简单。
但由于这个对理解golang之间利用通道通讯有一定的帮助,所以写下如下代码,发出来给大家看看。
思路简要:
最开始需要用一个带缓存的通道来触发开始操作,否则会引起死锁。然后用两个通道不断的交替进行接收与发送
package main
/**
用三个线程,交替输出abc,abc,abc...
*/
import (
"fmt"
"time"
)
func printc(c1 chan bool, c2 chan bool, s string) {
// 这个判断不能少,否则会乱套,只有在当前接收有效时,才向下一个通道发送数据
if _, ok := <-c1; ok {
fmt.Println(s)
c2 <- true
}
}
func main() {
// c1 使用带缓存的通道
c1 := make(chan bool, 1)
c2 := make(chan bool)
c3 := make(chan bool)
defer func() {
close(c1)
close(c2)
close(c3)
fmt.Println("end")
}()
// 开始触发通道 c1
c1 <- true
// 为了简单表示,这里只打印5次
for range make([]struct{}, 5) {
go printc(c1, c2, "a")
go printc(c2, c3, "b")
go printc(c3, c1, "c")
time.Sleep(time.Second)
}
}
在通道的接收发送中,我们需要理解一点通道的底层实现原理,那就是接收操作
一定会在发送操作完成
前完成,所以不要担心不会打印。通用一点,就是第K个接收操作一定会在第K+C个发送操作完成
之前完成。C是通道缓冲大小。