go之channel关闭与广播

简介: go之channel关闭与广播

一、使用channel创建消息生产者、消费者

 import (
  "fmt"
  "sync"
  "testing"
)
 
//生产者
func dataProducer(ch chan int, wg *sync.WaitGroup) {
  go func() {
    for i := 0; i < 10; i++ {
      //给通道添加数据
      ch <- i
    }
    //关闭channel,向关闭的channel发送数据,会导致panic
    close(ch)
    //ch <- -1 //panic: send on closed channel
    wg.Done()
  }()
}
 
//消费者
func dataReceiver(ch chan int, wg *sync.WaitGroup) {
  go func() {
    for {
      //从通道取数据,ok为bool值,true表示正常接收,false表示通道关闭
      //关闭通道,接收数据,返回零值
      if data, ok := <-ch; ok {
        fmt.Println(data)
      } else {
        break
      }
    }
    wg.Done()
  }()
}
 
func TestCloseChannel(t *testing.T) {
  var wg sync.WaitGroup
  //创建通道
  ch := make(chan int)
  wg.Add(1)
  //生成数据
  dataProducer(ch, &wg)
  wg.Add(1)
  //消费数据
  dataReceiver(ch, &wg)
  wg.Add(1)
  //消费数据
  dataReceiver(ch, &wg)
  wg.Wait()
}
=== RUN   TestCloseChannel
0
2
3
4
5
6
7
8
9
1
--- PASS: TestCloseChannel (0.00s)
PASS

二、使用channel关闭任务

 
import (
  "fmt"
  "testing"
  "time"
)
 
//任务是否已被取消
//实现原理:
//检查是否从 channel 收到一个消息,如果收到一个消息,我们就返回 true,代表任务已经被取消了
//当没有收到消息,channel 会被阻塞,多路选择机制就会走到 default 分支上去。
func isCanlled(cancelChan chan struct{}) bool {
  select {
  //是否收到消息
  case <-cancelChan:
    return true
  default:
    return false
  }
}
func cancel_1(cancelChan chan struct{}) {
  //struct{}空结构 struct{}{}实例化空结构
  cancelChan <- struct{}{}
}
 
//执行任务取消
//因为 close() 是一个广播机制,所以所有的协程都会收到消息
func cancel_2(cancel chan struct{}) {
  // close(cancel)会使所有处于处于阻塞等待状态的消息接收者(<-cancelChan)收到消息
  close(cancel)
}
func TestCancel(t *testing.T) {
  cancelChan := make(chan struct{}, 0)
  for i := 0; i < 5; i++ {
    go func(i int, cancelCh chan struct{}) {
      for {
        if isCanlled(cancelCh) {
          break
        }
        time.Sleep(time.Millisecond * 5)
      }
      fmt.Println(i, "Canceled")
    }(i, cancelChan)
  }
  //只有一个被取消
  //cancel_1(cancelChan)
  //全部被取消
  cancel_2(cancelChan)
  time.Sleep(time.Second * 1)
}
=== RUN   TestCancel
2 Canceled
1 Canceled
3 Canceled
4 Canceled
0 Canceled
--- PASS: TestCancel (1.01s)
PASS

三、使用Context取消关闭任务

import (
  "context"
  "fmt"
  "testing"
  "time"
)
 
//context就是用于管理相关任务的上下文,包含了共享值的传递,超时,取消通知
func isCanlled(ctx context.Context) bool {
  select {
  //Done方法返回一个信道(channel),当Context被撤销或过期时,该信道是关闭的,即它是一个表示Context是否已关闭的信号。
  //当Done信道关闭后,Err方法表明Context被撤的原因。
  case <-ctx.Done():
    return true
  default:
    return false
  }
}
 
func TestCancel(t *testing.T) {
  ctx, cancel := context.WithCancel(context.Background())
  for i := 0; i < 5; i++ {
    go func(i int, ctx context.Context) {
      for {
        if isCanlled(ctx) {
          break
        }
        time.Sleep(time.Millisecond * 5)
      }
      fmt.Println(i, "Canceled")
    }(i, ctx)
  }
  cancel()
  time.Sleep(time.Second * 1)
}
=== RUN   TestCancel
4 Canceled
0 Canceled
1 Canceled
2 Canceled
3 Canceled
--- PASS: TestCancel (1.02s)
PASS
相关文章
|
1月前
|
存储 Go 开发者
Go语言中的并发编程与通道(Channel)的深度探索
本文旨在深入探讨Go语言中并发编程的核心概念和实践,特别是通道(Channel)的使用。通过分析Goroutines和Channels的基本工作原理,我们将了解如何在Go语言中高效地实现并行任务处理。本文不仅介绍了基础语法和用法,还深入讨论了高级特性如缓冲通道、选择性接收以及超时控制等,旨在为读者提供一个全面的并发编程视角。
|
1月前
|
安全 Go 数据处理
Go语言中的并发编程:掌握goroutine和channel的艺术####
本文深入探讨了Go语言在并发编程领域的核心概念——goroutine与channel。不同于传统的单线程执行模式,Go通过轻量级的goroutine实现了高效的并发处理,而channel作为goroutines之间通信的桥梁,确保了数据传递的安全性与高效性。文章首先简述了goroutine的基本特性及其创建方法,随后详细解析了channel的类型、操作以及它们如何协同工作以构建健壮的并发应用。此外,还介绍了select语句在多路复用中的应用,以及如何利用WaitGroup等待一组goroutine完成。最后,通过一个实际案例展示了如何在Go中设计并实现一个简单的并发程序,旨在帮助读者理解并掌
|
1月前
|
安全 Go 调度
探索Go语言的并发模型:goroutine与channel
在这个快节奏的技术世界中,Go语言以其简洁的并发模型脱颖而出。本文将带你深入了解Go语言的goroutine和channel,这两个核心特性如何协同工作,以实现高效、简洁的并发编程。
|
1月前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
2月前
|
安全 Go 调度
探索Go语言的并发之美:goroutine与channel
在这个快节奏的技术时代,Go语言以其简洁的语法和强大的并发能力脱颖而出。本文将带你深入Go语言的并发机制,探索goroutine的轻量级特性和channel的同步通信能力,让你在高并发场景下也能游刃有余。
|
2月前
|
存储 安全 Go
探索Go语言的并发模型:Goroutine与Channel
在Go语言的多核处理器时代,传统并发模型已无法满足高效、低延迟的需求。本文深入探讨Go语言的并发处理机制,包括Goroutine的轻量级线程模型和Channel的通信机制,揭示它们如何共同构建出高效、简洁的并发程序。
|
2月前
|
存储 Go 调度
深入理解Go语言的并发模型:goroutine与channel
在这个快速变化的技术世界中,Go语言以其简洁的并发模型脱颖而出。本文将带你穿越Go语言的并发世界,探索goroutine的轻量级特性和channel的同步机制。摘要部分,我们将用一段对话来揭示Go并发模型的魔力,而不是传统的介绍性文字。
|
2月前
|
安全 Go 调度
探索Go语言的并发模型:Goroutine与Channel的魔力
本文深入探讨了Go语言的并发模型,不仅解释了Goroutine的概念和特性,还详细讲解了Channel的用法和它们在并发编程中的重要性。通过实际代码示例,揭示了Go语言如何通过轻量级线程和通信机制来实现高效的并发处理。
|
2月前
|
安全 Go 调度
探索Go语言的并发之美:goroutine与channel的实践指南
在本文中,我们将深入探讨Go语言的并发机制,特别是goroutine和channel的使用。通过实际的代码示例,我们将展示如何利用这些工具来构建高效、可扩展的并发程序。我们将讨论goroutine的轻量级特性,channel的同步通信能力,以及它们如何共同简化并发编程的复杂性。
|
2月前
|
安全 Go 数据处理
掌握Go语言并发:从goroutine到channel
在Go语言的世界中,goroutine和channel是构建高效并发程序的基石。本文将带你一探Go语言并发机制的奥秘,从基础的goroutine创建到channel的同步通信,让你在并发编程的道路上更进一步。