Channel基础 #
一、Channel概述 #
Channel是goroutine之间通信的管道,遵循CSP(通信顺序进程)模型。
1.1 特点 #
- 线程安全
- 阻塞特性
- 类型安全
- 双向/单向
二、创建Channel #
2.1 make创建 #
go
ch := make(chan int) // 无缓冲通道
ch := make(chan int, 10) // 缓冲通道
2.2 零值 #
go
var ch chan int
fmt.Println(ch == nil) // true
三、发送与接收 #
3.1 发送数据 #
go
ch := make(chan int)
ch <- 10 // 发送
3.2 接收数据 #
go
v := <-ch // 接收
3.3 基本示例 #
go
func main() {
ch := make(chan string)
go func() {
ch <- "Hello"
}()
msg := <-ch
fmt.Println(msg) // Hello
}
3.4 双向通道 #
go
func main() {
ch := make(chan int)
go func() {
ch <- 42
}()
v := <-ch
fmt.Println(v)
}
四、无缓冲通道 #
4.1 特点 #
- 发送和接收同步进行
- 发送阻塞直到接收
- 接收阻塞直到发送
4.2 同步通信 #
go
func main() {
ch := make(chan int)
go func() {
fmt.Println("Sending...")
ch <- 1
fmt.Println("Sent")
}()
time.Sleep(time.Second)
v := <-ch
fmt.Println("Received:", v)
}
4.3 握手模式 #
go
func worker(done chan bool) {
fmt.Println("Working...")
time.Sleep(time.Second)
done <- true
}
func main() {
done := make(chan bool)
go worker(done)
<-done
fmt.Println("Done")
}
五、缓冲通道 #
5.1 特点 #
- 有固定容量
- 缓冲未满时发送不阻塞
- 缓冲不为空时接收不阻塞
5.2 基本用法 #
go
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
// ch <- 4 // 阻塞,缓冲已满
fmt.Println(<-ch) // 1
fmt.Println(<-ch) // 2
5.3 容量与长度 #
go
ch := make(chan int, 3)
fmt.Println(cap(ch)) // 3
fmt.Println(len(ch)) // 0
ch <- 1
ch <- 2
fmt.Println(len(ch)) // 2
5.4 异步处理 #
go
func main() {
ch := make(chan int, 100)
go func() {
for i := 0; i < 100; i++ {
ch <- i
}
close(ch)
}()
for v := range ch {
fmt.Println(v)
}
}
六、关闭Channel #
6.1 close函数 #
go
ch := make(chan int)
ch <- 1
close(ch)
6.2 检测关闭 #
go
ch := make(chan int)
close(ch)
v, ok := <-ch
fmt.Println(v, ok) // 0 false
6.3 range遍历 #
go
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
for v := range ch {
fmt.Println(v)
}
6.4 关闭规则 #
- 只能关闭一次
- 只能在发送方关闭
- 关闭后不能再发送
- 关闭后可以继续接收
go
ch := make(chan int)
close(ch)
// close(ch) // panic: close of closed channel
// ch <- 1 // panic: send on closed channel
七、单向Channel #
7.1 只发送通道 #
go
func send(ch chan<- int) {
ch <- 1
// v := <-ch // 错误:不能接收
}
7.2 只接收通道 #
go
func receive(ch <-chan int) {
v := <-ch
// ch <- 1 // 错误:不能发送
}
7.3 类型转换 #
go
func main() {
ch := make(chan int)
go send(ch)
receive(ch)
}
func send(ch chan<- int) {
ch <- 1
}
func receive(ch <-chan int) {
<-ch
}
八、实际应用 #
8.1 生产者消费者 #
go
func producer(ch chan<- int) {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
}
func consumer(ch <-chan int) {
for v := range ch {
fmt.Println(v)
}
}
func main() {
ch := make(chan int, 5)
go producer(ch)
consumer(ch)
}
8.2 任务队列 #
go
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
results <- j * 2
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
for i := 0; i < 3; i++ {
go worker(i, jobs, results)
}
for i := 0; i < 10; i++ {
jobs <- i
}
close(jobs)
for i := 0; i < 10; i++ {
fmt.Println(<-results)
}
}
8.3 信号通知 #
go
func main() {
done := make(chan struct{})
go func() {
time.Sleep(time.Second)
close(done)
}()
<-done
fmt.Println("Done")
}
九、常见错误 #
9.1 死锁 #
go
func main() {
ch := make(chan int)
ch <- 1 // 死锁:无接收者
}
9.2 向关闭的通道发送 #
go
ch := make(chan int)
close(ch)
ch <- 1 // panic
9.3 关闭nil通道 #
go
var ch chan int
close(ch) // panic
十、最佳实践 #
10.1 由发送方关闭 #
go
func sender(ch chan int) {
defer close(ch)
ch <- 1
}
10.2 使用range接收 #
go
for v := range ch {
// 处理v
}
10.3 使用缓冲提高性能 #
go
ch := make(chan int, 100) // 适当的缓冲大小
十一、总结 #
Channel要点:
| 类型 | 说明 |
|---|---|
| 无缓冲 | 同步通信 |
| 缓冲 | 异步通信 |
| 单向 | 限制方向 |
关键点:
- make创建:使用make创建channel
- 阻塞特性:无缓冲通道同步阻塞
- 缓冲通道:提高性能,减少阻塞
- 关闭规则:发送方关闭,只能关闭一次
- 单向通道:提高类型安全性
准备好学习Channel操作了吗?让我们进入下一章!
最后更新:2026-03-26