Golang 通道类型

266 阅读2分钟

通道类型

通道(channel)是用来传递数据的一个数据结构 通道可用于两个 goroutine 之间通过传递一个指定类型的值来同步运行和通讯 操作符 <- 用于指定通道的方向,发送或接收;如果未指定方向,则为双向通道

默认情况下,通道是不带 缓冲区 的;发送端发送数据,同时必须有接收端相应的接收数据 带 缓冲区 的通道允许发送端的数据发送和接收端的数据获取处于异步状态,就是说发送端发送的数据可以放到 缓冲区 里面,可以等待接收端获取数据,而不是立刻需要接收端获取数据 不过由于 缓冲区 的大小是有限的,所以还是必须有接收端接收数据的,否则 缓冲区 一满,发送端就无法发送数据了

ps: 如果通道不带 缓冲区,发送方会阻塞直到接收方从通道中获取了数据 如果通道是带 缓冲区 的,发送方会阻塞直到发送的数据被拷贝到 缓冲区 内 如果 缓冲区 已满,发送方会阻塞直到接收方获取到一个值 接收方在有值可以接收之前会一直阻塞

使用 make、chan 关键字,创建通道,make 的第二个参数可以指定 缓存区 大小

ch := make(chan int)         // 创建无缓冲通道
ch := make(chan int100)   // 创建有缓冲通道,缓冲区大小为 100

ch <- v       // 把 v 发送到通道 ch 
v := <-ch     // 从 ch 接收数据,并赋值给 v

无缓冲区通道

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    c <- sum // 把 sum 发送到通道 c
}

func main() {
    s := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int)
    go sum(s[:len(s)/2], c)
    go sum(s[len(s)/2:], c)
    x, y := <-c, <-c // 从通道 c 中接收

    fmt.Println(x, y, x+y)
}

有缓冲区通道

func fibonacci(n int, c chan int) {
    x, y := 1, 1
    for i := 0; i < n; i++ {
        c <- x
        x, y = y, x+y
    }
    close(c)
}

func main() {
    c := make(chan int, 10)
    go fibonacci(cap(c), c)
    // range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个
    // 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据
    // 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不
    // 会结束,从而在接收第 11 个数据的时候就阻塞了。
    for i := range c {
        fmt.Println(i)
    }
}