Golang Channel范围循环

在使用Golang的channel进行范围循环时遇到了问题。代码如下:

ch := make(chan int)
go func() {
    for i := 0; i < 5; i++ {
        ch <- i
    }
    close(ch)
}()

for v := range ch {
    fmt.Println(v)
}

为什么必须在goroutine中显式调用close(ch),否则程序会报死锁错误?如果发送端不关闭channel,有什么办法可以让接收端安全地退出循环而不导致死锁?

2 回复

Golang中,使用for range循环遍历channel会持续接收数据,直到channel被关闭。若未关闭channel,会导致死锁。示例:

ch := make(chan int)
go func() {
    for i := 0; i < 3; i++ {
        ch <- i
    }
    close(ch)
}()
for v := range ch {
    fmt.Println(v)
}

更多关于Golang Channel范围循环的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,使用range关键字可以方便地遍历(循环)channel中的元素,直到channel被关闭。这是一种常见的并发模式,用于从channel中持续接收数据。

语法

for value := range ch {
    // 处理value
}
  • ch:要遍历的channel。
  • value:每次从channel接收到的值。
  • 循环会持续从channel接收数据,直到channel被关闭(close(ch)),然后自动退出。

示例代码

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)

    // 启动一个goroutine向channel发送数据
    go func() {
        for i := 1; i <= 5; i++ {
            ch <- i
            time.Sleep(500 * time.Millisecond) // 模拟处理延迟
        }
        close(ch) // 发送完成后关闭channel
    }()

    // 使用range循环接收数据
    for num := range ch {
        fmt.Println("Received:", num)
    }

    fmt.Println("Channel closed, loop exited.")
}

关键点

  1. 必须关闭channel:如果发送方不关闭channel,range循环会一直阻塞等待,导致goroutine泄漏或死锁。
  2. 适用于缓冲和非缓冲channel:两种类型都支持range循环。
  3. 单向channel:只能对可读channel(<-chan T)使用range循环。

注意事项

  • 确保在适当的时候关闭channel,避免资源泄漏。
  • 如果多个goroutine向同一个channel发送数据,需协调关闭时机(例如使用sync.WaitGroup)。

这是一种高效、简洁的并发数据接收方式。

回到顶部