Go channel被关闭时的广播机制,以及遍历未关闭channel时会导致死锁阻塞问题

简介: Go channel被关闭时的广播机制,以及遍历未关闭channel时会导致死锁阻塞问题

Go channel特性

  • Go channel的广播机制

当一个channel被 close时,所有通过select监听这个channel IO事件的goroutine,都会收到相关事件:当前监听的channel已关闭。

func main() {
    ch := make(chan int, 2)
    for i := 1; i <= 2; i++ {
        ch <- i
    }

    close(ch) // 关闭channel,v1、v2、v3都会收到相关事件

    // Go channel的广播机制:三个select都监听到了相关事件
    select {
    case v1 := <-ch:
        fmt.Println("v1: ", v1) // 输出:1
    }

    select {
    case v2 := <-ch:
        fmt.Println("v2: ", v2) // 输出:2
    }

    select {
    case v3 := <-ch:
        fmt.Println("v3: ", v3) // 输出:0,channel读完为空时,后续读值都为0值
    }
}
  • 遍历未关闭的channel时会导致死锁阻塞:

如果不close掉channel直接range遍历是会发生死锁的,原因是 当for循环读完channel的10个值之后会继续尝试读取下一个,而由于channel为空又没关闭,会一直阻塞形成死锁

func main() {
    ch := make(chan int, 10)
    for i := 1; i <= 10; i++ {
        ch <- i
    }

    // 遍历时,如果channel没有关闭,则会出现deadlock错误
    // close(ch) // 注释掉,不关闭

    // channel遍历
    fmt.Println("start...")

    for v := range ch {
        fmt.Println("v: ", v) // 输出1、2后就会阻塞
    }

    fmt.Println("end...")
}

/* 
仅输出:
start...
v:  1
v:  2
*/
  • close后的channel仍然可读,先读出接收到的有效数据,直至channel数据读完后,后续都会读到对应类型的零值,比如:int对应数值0string对应空字符串 ...
  • 但是如果通过range读取,channel关闭后会直接跳出for循环: 通过i, ok := <-c中的ok为true还是false,来查看channel的状态,判断值是否有效。
目录
相关文章
|
1月前
|
Go
go语言中遍历映射(map)
go语言中遍历映射(map)
46 8
|
1月前
|
存储 Go 索引
go语言中遍历字符串
go语言中遍历字符串
46 5
|
1月前
|
存储 Go 开发者
Go语言中的并发编程与通道(Channel)的深度探索
本文旨在深入探讨Go语言中并发编程的核心概念和实践,特别是通道(Channel)的使用。通过分析Goroutines和Channels的基本工作原理,我们将了解如何在Go语言中高效地实现并行任务处理。本文不仅介绍了基础语法和用法,还深入讨论了高级特性如缓冲通道、选择性接收以及超时控制等,旨在为读者提供一个全面的并发编程视角。
|
23天前
|
Go
go语言for遍历映射(map)
go语言for遍历映射(map)
32 12
|
22天前
|
Go 索引
go语言使用索引遍历
go语言使用索引遍历
29 9
|
23天前
|
Go
go语言for 遍历字符串
go语言for 遍历字符串
29 8
|
24天前
|
存储 Go 索引
go语言使用for循环遍历
go语言使用for循环遍历
34 7
|
1月前
|
Go
go语言中遍历映射同时遍历键和值
go语言中遍历映射同时遍历键和值
26 7
|
27天前
|
Go 索引
go语言遍历字符串
go语言遍历字符串
26 3
|
27天前
|
存储 Go
go语言 遍历映射(map)
go语言 遍历映射(map)
33 2