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要点:

类型 说明
无缓冲 同步通信
缓冲 异步通信
单向 限制方向

关键点:

  1. make创建:使用make创建channel
  2. 阻塞特性:无缓冲通道同步阻塞
  3. 缓冲通道:提高性能,减少阻塞
  4. 关闭规则:发送方关闭,只能关闭一次
  5. 单向通道:提高类型安全性

准备好学习Channel操作了吗?让我们进入下一章!

最后更新:2026-03-26