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
相关文章
|
5月前
|
存储 安全 Java
Go 基础数据结构的底层原理(slice,channel,map)
Go 基础数据结构的底层原理(slice,channel,map)
86 0
|
2月前
|
消息中间件 Kafka Go
从Go channel中批量读取数据
从Go channel中批量读取数据
|
2月前
|
缓存 并行计算 Go
go 语言中 channel 的简单介绍
go 语言中 channel 的简单介绍
|
2月前
|
Go
在go中监听多个channel
在go中监听多个channel
|
4月前
|
存储 Go
Go 语言当中 CHANNEL 缓冲
Go 语言当中 CHANNEL 缓冲
|
4月前
|
Go
go之channel任意任务完成、全部任务完成退出
go之channel任意任务完成、全部任务完成退出
|
5月前
|
负载均衡 Go 调度
使用Go语言构建高性能的Web服务器:协程与Channel的深度解析
在追求高性能Web服务的今天,Go语言以其强大的并发性能和简洁的语法赢得了开发者的青睐。本文将深入探讨Go语言在构建高性能Web服务器方面的应用,特别是协程(goroutine)和通道(channel)这两个核心概念。我们将通过示例代码,展示如何利用协程处理并发请求,并通过通道实现协程间的通信和同步,从而构建出高效、稳定的Web服务器。
|
5月前
|
设计模式 缓存 安全
一篇文章带你吃透Go语言的Atomic和Channel--实战方法
一篇文章带你吃透Go语言的Atomic和Channel--实战方法
82 0
|
5月前
|
存储 Go
|
5月前
|
安全 Go 调度
Go语言的并发编程:goroutine和channel详解
Go语言的并发编程:goroutine和channel详解
185 2