通道(channel)
通道(channel)是用来传递数据的一个数据结构。
通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯。操作符 <- 用于指定通道的方向,发送或接收。如果未指定方向,则为双向通道。
这个意思很明确,goroutine是支持多线程,channel作为一个管道接收数据输出数据,遵循先进先出原则。
来个例子感受下,创建三个goroutine,都传入channel值
func main() {
ch := make(chan string)
go chanaction1(ch)
time.Sleep(time.Second)
go chanaction2(ch)
time.Sleep(time.Second)
go chanaction3(ch)
x,y,z := <-ch, <-ch, <-ch
fmt.Println(x,y,z)
}
func chanaction1(ch chan string) {
ch <- "1"
}
func chanaction2(ch chan string) {
ch <- "2"
}
func chanaction3(ch chan string) {
ch <- "3"
}
输出就是:
这样就可以异步加入channel值了,而且输出顺序和输入顺序一致,但是有人会说,三个协程可能会阻塞,好吧,那我们拿一个协程来试,代码如下:
func main() {
ch := make(chan string)
go chanaction1(ch)
x,y,z := <-ch, <-ch, <-ch
fmt.Println(x,y,z)
}
func chanaction1(ch chan string) {
ch <- "1"
ch <- "2"
ch <- "3"
}
重新执行,结果还是输出1,2,3。
一般的协程和channel没有这么简单用法,再举个比较常见的用法:线程阻塞等待channel通道结果,
如,a := <-ch,当通道ch中没有值,则当前协程一直阻塞,直到ch接收新数据,如:执行ch <- 1后,线程不再阻塞,好,在上面的基础添加测试代码
func main() {
ch := make(chan string)
go chanaction1(ch)
x,y,z := <-ch, <-ch, <-ch
fmt.Println(x,y,z)
go gorutine2(ch)
a := <-ch
fmt.Println(a)
}
func chanaction1(ch chan string) {
ch <- "1"
ch <- "2"
ch <- "3"
}
func gorutine2(ch chan string) {
for i := 0; i<5000; i++ {
time.Sleep(time.Second *1)
fmt.Println("----等待----")
if i>= 5 {
ch <- "end"
return
}
}
}
看效果: