go channel

2023-09-13 08:03:00 浏览数 (2)

Go 语言中的管道(channel)是一种特殊的类型,遵循先入先出的规则,保证收发数据的顺序。每一个管道都有具体的类型,也就是声明channel的时候需要为其指定元素类型。

创建管道

管道需要使用make函数初始化之后才能使用。创建管道的格式如下:

代码语言:javascript复制
make(chan 管道类型, 缓冲大小)

其中缓冲大小是可选的。

管道操作

创建一个管道

代码语言:javascript复制
ch := make(chan int)

发送数据

代码语言:javascript复制
ch <- 10

接收数据

代码语言:javascript复制
i := <- ch
//  接收数据并忽略结果
<- ch

关闭管道

代码语言:javascript复制
close(ch)

管道特点

  • 对关闭的管道发送数据会导致panic
  • 对关闭的管道能够正常接收数据,直到管道为空
  • 从关闭且没有值的管道,能够接收该管道类型对应的零值
  • 关闭一个已关闭的管道会导致panic

无缓冲管道

无缓冲的通道只有在有人接收值的时候才能发送值,否则会引发panic。 下面的代码会引发panic。

代码语言:javascript复制
package main

func main() {
    ch := make(chan int)
    ch <- 1
    ch <- 2
    <-ch
    <-ch
    close(ch)
}

下面的代码会阻塞而引发panic。

代码语言:javascript复制
package main

func main() {
    ch := make(chan int)
    <-ch
    <-ch
    ch <- 1
    ch <- 2
    close(ch)
}

一般使用goroutine接收数据。

代码语言:javascript复制
package main

func main() {
    ch := make(chan int)
    go func() {
        <-ch
        <-ch
    }()
    ch <- 1
    ch <- 2
    close(ch)
}

有缓冲通道

缓冲通道能够暂时储存数据,但当储存的数据超过容量时,依然会引发panic。

代码语言:javascript复制
package main

func main() {
    ch := make(chan int, 2)
    ch <- 1
    ch <- 2
    <-ch
    <-ch
    close(ch)
}

优雅的取值

通过for循环和range可以从管道中接收数据,当管道关闭时,自动退出循环。

代码语言:javascript复制
package main

import "fmt"

func main() {
    ch := make(chan int)
    go func() {
        for i := range ch {
            fmt.Println(i)
        }
    }()
    ch <- 1
    ch <- 2
    close(ch)
}

单向管道

普通管道:chan int 只能发送的管道:chan <- int 只能接收的管道:<- chan

0 人点赞