六:什么是 channel 管道
它是一个数据管道,可以往里面写数据,从里面读数据。
channel 是 goroutine 之间数据通信桥梁,而且是线程安全的。
channel 遵循先进先出原则。
写入,读出数据都会加锁。
channel 可以分为 3 种类型:
只读 channel,单向 channel
只写 channel,单向 channel
可读可写 channel操作 | nil的channel | 正常channel | 已关闭的channel | 读 <-ch | 阻塞 | 成功或阻塞 | 读到零值 | 写 ch<- | 阻塞 | 成功或阻塞 | panic | 关闭 close(ch) | panic | 成功 | panic |
channel 还可按是否带有缓冲区分为:
带缓冲区的 channel,定义了缓冲区大小,可以存储多个数据
不带缓冲区的 channel,只能存一个数据,并且只有当该数据被取出才能存下一个数据
不带缓冲区channel示例:- package main
- import "fmt"
- func main() {
- ch := make(chan int) // 无缓冲的channel
- go unbufferChan(ch)
- for i := 0; i < 5; i++ {
- fmt.Println("receive ", <-ch) // 读出值
- }
- }
- func unbufferChan(ch chan int) {
- for i := 0; i < 5; i++ {
- fmt.Println("send ", i)
- ch <- i // 写入值
- println("write: ", i)
- }
- }
- 运行结果如下:
- send 0
- write: 0
- send 1
- receive 0
- receive 1
- write: 1
- send 2
- write: 2
- receive 2
- send 3
- write: 3
- receive 3
- send 4
- write: 4
- receive 4
- Program exited.
复制代码 带缓冲区的channel示例:- package main
- import (
- "fmt"
- )
- var c = make(chan int, 5)
- func main() {
- go worker(1)
- for i := 1; i < 10; i++ {
- c <- i
- fmt.Println("write: ", i)
- }
- }
- func worker(id int) {
- for {
- fmt.Println("read: ", <-c)
- }
- }
- 运行结果:
- write: 1
- write: 2
- write: 3
- write: 4
- write: 5
- write: 6
- read: 1
- read: 2
- read: 3
- read: 4
- read: 5
- read: 6
- read: 7
- write: 7
- write: 8
- write: 9
- 想一想,为啥没有 read: 8, 9 的值呢?
复制代码 |