Go channel 关闭和广播

简介: Go channel 关闭和广播

Go channel 关闭和广播


Dont Communicate by sharing memory, sharing memory by communicate.
不要通过共享内存的方式通讯,要通过通讯的方式共享内存

Channel 基本概念


一个通道相当于 FIFO 的队列, 通道中各个元素之间都是严格按照发送的顺序队列,先发送的队列一定会被先接收,元素值的发送和传输和发送都使用到操作符 <-

channel 的关闭


  • 向关闭的 channel 发送数据, 会导致 panic
package main
import (
 "fmt"
 "sync"
 "testing"
)
func dataProducer(ch chan int, wg *sync.WaitGroup) {
 go func() {
  for i := 0; i < 11; i++ {
   ch <- i
  }
  wg.Done()
 }()
}
func dataConsumer(ch chan int , wg *sync.WaitGroup) {
 go func () {
  for i := 0; i < 10; i++ {
   data := <- ch
   fmt.Println(data)
  }
  close(ch)
  wg.Done()
 }()
}
func TestCloseChanner(t *testing.T) {
 var wg sync.WaitGroup
 ch := make(chan int)
 wg.Add(1)
 dataProducer(ch, &wg)
 wg.Add(1)
 dataConsumer(ch, &wg)
 wg.Wait()
}


运行结果


GOROOT=C:\Go #gosetup
GOPATH=D:\GoWorkSpace #gosetup
C:\Go\bin\go.exe test -c -o C:\Users\wangm\AppData\Local\Temp\___channel_close_test_go.exe GoProject/src/main/gobase/channel #gosetup
C:\Go\bin\go.exe tool test2json -t C:\Users\wangm\AppData\Local\Temp\___channel_close_test_go.exe -test.v -test.run ^\QTestCloseChanner\E$ #gosetup
=== RUN   TestCloseChanner
0
1
2
3
4
5
6
7
8
9
panic: send on closed channel
goroutine 20 [running]:
GoProject/src/main/gobase/channel.dataProducer.func1(0xc0000862a0, 0xc0000942b0)
 D:/GoWorkspaces/GoProject/src/main/gobase/channel/channel_close_test.go:12 +0x4a
created by GoProject/src/main/gobase/channel.dataProducer
 D:/GoWorkspaces/GoProject/src/main/gobase/channel/channel_close_test.go:10 +0x50
Process finished with exit code 1


  • v, ok <- ch; ok 为 bool 值, true 表示正常接收,false 表示通道关闭
  • 所有的 channel 接收者都会在 channel 关闭时,立刻从阻塞等待中返回且上述 ok 值 为 false 。这个广播机制被利用,进行多个订阅同时发送信号。

image.png

package main
import (
 "fmt"
 "sync"
 "testing"
)
func dataProducer(ch chan int, wg *sync.WaitGroup) {
 go func() {
  for i := 0; i < 10; i++ {
   ch <- i
  }
  close(ch)
  wg.Done()
 }()
}
func dataConsumer(ch chan int , wg *sync.WaitGroup) {
 go func () {
  for i := 0; i < 10; i++ {
   if data, ok := <- ch; ok {
    fmt.Println(data)
   } else {
    break
   }
  }
  wg.Done()
 }()
}
func TestCloseChanner(t *testing.T) {
 var wg sync.WaitGroup
 ch := make(chan int)
 wg.Add(1)
 dataProducer(ch, &wg)
 wg.Add(1)
 dataConsumer(ch, &wg)
 wg.Wait()
}

运行结果


GOROOT=C:\Go #gosetup
GOPATH=D:\GoWorkSpace #gosetup
C:\Go\bin\go.exe test -c -o C:\Users\wangm\AppData\Local\Temp\___channel_close_test_go.exe GoProject/src/main/gobase/channel #gosetup
C:\Go\bin\go.exe tool test2json -t C:\Users\wangm\AppData\Local\Temp\___channel_close_test_go.exe -test.v -test.run ^\QTestCloseChanner\E$ #gosetup
=== RUN   TestCloseChanner
0
1
2
3
4
5
6
7
8
9
--- PASS: TestCloseChanner (0.00s)
PASS
Process finished with exit code 0


测试代码


package main
import (
 "fmt"
 "sync"
 "testing"
)
func dataProducer(ch chan int, wg *sync.WaitGroup) {
 go func() {
  for i := 0; i < 10; i++ {
   ch <- i
  }
  close(ch)
  wg.Done()
 }()
}
func dataConsumer(ch chan int , wg *sync.WaitGroup) {
 go func () {
  for i := 0; i < 11; i++ {
   data := <- ch
   fmt.Println(data)
  }
  wg.Done()
 }()
}
func TestCloseChanner(t *testing.T) {
 var wg sync.WaitGroup
 ch := make(chan int)
 wg.Add(1)
 dataProducer(ch, &wg)
 wg.Add(1)
 dataConsumer(ch, &wg)
 wg.Wait()
}


运行结果:


GOPATH=D:\GoWorkSpace #gosetup
C:\Go\bin\go.exe test -c -o C:\Users\wangm\AppData\Local\Temp\___channel_close_test_go.exe GoProject/src/main/gobase/channel #gosetup
C:\Go\bin\go.exe tool test2json -t C:\Users\wangm\AppData\Local\Temp\___channel_close_test_go.exe -test.v -test.run ^\QTestCloseChanner\E$ #gosetup
=== RUN   TestCloseChanner
0
1
2
3
4
5
6
7
8
9
0
--- PASS: TestCloseChanner (0.00s)
PASS
Process finished with exit code 0
相关文章
|
3月前
|
存储 Go 开发者
Go语言中的并发编程与通道(Channel)的深度探索
本文旨在深入探讨Go语言中并发编程的核心概念和实践,特别是通道(Channel)的使用。通过分析Goroutines和Channels的基本工作原理,我们将了解如何在Go语言中高效地实现并行任务处理。本文不仅介绍了基础语法和用法,还深入讨论了高级特性如缓冲通道、选择性接收以及超时控制等,旨在为读者提供一个全面的并发编程视角。
111 50
|
3月前
|
安全 Go 数据处理
Go语言中的并发编程:掌握goroutine和channel的艺术####
本文深入探讨了Go语言在并发编程领域的核心概念——goroutine与channel。不同于传统的单线程执行模式,Go通过轻量级的goroutine实现了高效的并发处理,而channel作为goroutines之间通信的桥梁,确保了数据传递的安全性与高效性。文章首先简述了goroutine的基本特性及其创建方法,随后详细解析了channel的类型、操作以及它们如何协同工作以构建健壮的并发应用。此外,还介绍了select语句在多路复用中的应用,以及如何利用WaitGroup等待一组goroutine完成。最后,通过一个实际案例展示了如何在Go中设计并实现一个简单的并发程序,旨在帮助读者理解并掌
|
3月前
|
安全 Go 调度
探索Go语言的并发模型:goroutine与channel
在这个快节奏的技术世界中,Go语言以其简洁的并发模型脱颖而出。本文将带你深入了解Go语言的goroutine和channel,这两个核心特性如何协同工作,以实现高效、简洁的并发编程。
|
3月前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
8月前
|
Go
go之channel关闭与广播
go之channel关闭与广播
|
4月前
|
安全 Go 调度
探索Go语言的并发之美:goroutine与channel
在这个快节奏的技术时代,Go语言以其简洁的语法和强大的并发能力脱颖而出。本文将带你深入Go语言的并发机制,探索goroutine的轻量级特性和channel的同步通信能力,让你在高并发场景下也能游刃有余。
|
4月前
|
存储 安全 Go
探索Go语言的并发模型:Goroutine与Channel
在Go语言的多核处理器时代,传统并发模型已无法满足高效、低延迟的需求。本文深入探讨Go语言的并发处理机制,包括Goroutine的轻量级线程模型和Channel的通信机制,揭示它们如何共同构建出高效、简洁的并发程序。
|
4月前
|
存储 Go 调度
深入理解Go语言的并发模型:goroutine与channel
在这个快速变化的技术世界中,Go语言以其简洁的并发模型脱颖而出。本文将带你穿越Go语言的并发世界,探索goroutine的轻量级特性和channel的同步机制。摘要部分,我们将用一段对话来揭示Go并发模型的魔力,而不是传统的介绍性文字。
|
4月前
|
安全 Go 调度
探索Go语言的并发模型:Goroutine与Channel的魔力
本文深入探讨了Go语言的并发模型,不仅解释了Goroutine的概念和特性,还详细讲解了Channel的用法和它们在并发编程中的重要性。通过实际代码示例,揭示了Go语言如何通过轻量级线程和通信机制来实现高效的并发处理。
|
4月前
|
安全 Go 调度
探索Go语言的并发之美:goroutine与channel的实践指南
在本文中,我们将深入探讨Go语言的并发机制,特别是goroutine和channel的使用。通过实际的代码示例,我们将展示如何利用这些工具来构建高效、可扩展的并发程序。我们将讨论goroutine的轻量级特性,channel的同步通信能力,以及它们如何共同简化并发编程的复杂性。