通道(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"
}
输出就是:

image.png
这样就可以异步加入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
        }
    }
}
看效果:

image.png

image.png