概念及作用

channel是一个数据类型,用于实现同步,用于两个协程之间交换数据。goroutine奉行通过通信来共享内存,而不是共享内存来通信。
引用类型channel是CSP模式的具体实现,用于多个goroutine通讯。其内部实现了同步,确保并发安全。

创建及使用
每个channel在创建的时候必须指定一个类型,指定的类型是任意的。

ch := make(chan int)   //使用内置的make函数,可以创建一个channel类型
// 发送数据到channel
ch <- 1
// 从channel接受数据
x := <- ch

案例举例(一)

①创建channel前

package main

import (
    "fmt"
    "time"
)

//定义一个打印机,参数为字符串,按每个字符打印
//打印机属于公共资源
func Printer(str string) {
    for _, data := range str {
        fmt.Printf("%c", data)
        time.Sleep(time.Second)
    }
    fmt.Printf("\n")
}

func person1() {
    Printer("hello")
}

func person2() {
    Printer("world")
}

func main() {
    //新建2个协程,代表2个人,2个人同时使用打印机
    go person1()
    go person2()

    //特地不让主协程结束,死循环
    for {

    }
}
//结果
hwoerllldo   //交叉执行

②创建channel后(注意channel变量和调用的先后顺序)

package main

import (
    "fmt"
    "time"
)

//全局变量,创建一个channel
var ch = make(chan int)

//定义一个打印机,参数为字符串,按每个字符打印
//打印机属于公共资源
func Printer(str string) {
    for _, data := range str {
        fmt.Printf("%c", data)
        time.Sleep(time.Second)
    }
    fmt.Printf("\n")
}

//person1执行完后,才能到person2执行
func person1() {
    Printer("hello")
    ch <- 666 //给管道写数据,发送
}

func person2() {
    <-ch //从管道取数据,接收,如果通道没有数据他就会阻塞
    Printer("world")
}

func main() {
    //新建2个协程,代表2个人,2个人同时使用打印机
    go person1()
    go person2()

    //特地不让主协程结束,死循环
    for {

    }
}
hello
world

案例举例(二)

package main

import (
    "fmt"
)

func main() {
    ch := make(chan string)
    go func() {
        fmt.Println("aaaaaaaaaa")
        str := <-ch // 在执行到这一步的时候main goroutine才会停止阻塞
        fmt.Println("取出channel的数据" + str)
    }()
    fmt.Println("bbbbbbbbbb")
    ch <- "hello" // 如果没有其他goroutine来取走这个数据,main goroutine挂起,直到其它gorouteine把数据拿走(这里会暂时阻塞)
    fmt.Println("cccccccccc")
}
bbbbbbbbbb
aaaaaaaaaa
取出channel的数据hello
cccccccccc