Go语言通道之缓冲通道

 更新时间:2022年07月16日 09:22:52   作者:奋斗的大橙子  
这篇文章介绍了Go语言通道之缓冲通道,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

前文为大家讲解了Go语言通道之无缓冲通道

有缓冲的通道相比于无缓冲通道,多了一个缓存的功能,如下图描述的一样:

从图上可以明显看到和无缓冲通道的区别,无缓冲必须两个Goroutine都进入通道才能进行数据的交换,这个不用,如果数据有,直接就能拿走。

package ChannelDemo

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

const (
    numberGoroutines = 4
    taskLoad         = 10
)

var bufferWg sync.WaitGroup

func init() {
    rand.Seed(time.Now().Unix())
}

func main() {
    //创建了一个10任务的缓冲通道
    tasks := make(chan string, taskLoad)
    bufferWg.Add(numberGoroutines)

    //创建4个Goroutine
    for gr := 1; gr <= numberGoroutines; gr++ {
        go worker(tasks, gr)
    }

    //向缓冲通道中放入数据
    for post := 1; post <= taskLoad; post++ {
        tasks <- fmt.Sprintf("Task : %d", post)
    }

    close(tasks)

    bufferWg.Wait()
}

func worker(tasks chan string, worker int) {
    defer bufferWg.Done()

    for {
        task, ok := <-tasks
        if !ok {
            fmt.Printf("Worker: %d : 结束工作 \n", worker)
            return
        }

        fmt.Printf("Worker: %d : 开始工作 %s\n", worker, task)

        //随机处理一下工作的时间
        sleep := rand.Int63n(100)
        time.Sleep(time.Duration(sleep) * time.Millisecond)

        fmt.Printf("Worker: %d : 完成工作 %s\n", worker, task)
    }
}

运行结果:

Worker: 3 : 开始工作 Task : 4
Worker: 2 : 开始工作 Task : 2
Worker: 1 : 开始工作 Task : 1
Worker: 4 : 开始工作 Task : 3
Worker: 4 : 完成工作 Task : 3
Worker: 4 : 开始工作 Task : 5
Worker: 2 : 完成工作 Task : 2
Worker: 2 : 开始工作 Task : 6
Worker: 3 : 完成工作 Task : 4
Worker: 3 : 开始工作 Task : 7
Worker: 1 : 完成工作 Task : 1
Worker: 1 : 开始工作 Task : 8
Worker: 3 : 完成工作 Task : 7
Worker: 3 : 开始工作 Task : 9
Worker: 1 : 完成工作 Task : 8
Worker: 1 : 开始工作 Task : 10
Worker: 4 : 完成工作 Task : 5
Worker: 4 : 结束工作
Worker: 3 : 完成工作 Task : 9
Worker: 3 : 结束工作
Worker: 2 : 完成工作 Task : 6
Worker: 2 : 结束工作
Worker: 1 : 完成工作 Task : 10
Worker: 1 : 结束工作 

因为哪一个worker先从通道中取值有系统自己进行调度的,所以每次运行的结果稍微不同,但是相同的是10个任务被4个协程有条不紊的完成了

注意:main中有一句代码 Close(tasks) 关闭通道的代码非常重要。当通道关闭后,goroutine 依旧可以从通道接收数据,但是不能再向通道里发送数据。

能够从已经关闭的通道接收数据这一点非常重要,因为这允许通道关闭后依旧能取出其中缓冲的全部值,而不会有数据丢失.

总结

无缓冲的通道保证同时交换数据,而有缓冲的通道不做这种保证。

到此这篇关于Go语言通道之缓冲通道的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Go语言实现基于websocket浏览器通知功能

    Go语言实现基于websocket浏览器通知功能

    这篇文章主要介绍了Go语言实现基于websocket浏览器通知功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • Golang 在gin框架中如何使用JWT鉴权

    Golang 在gin框架中如何使用JWT鉴权

    JWT,全称 JSON Web Token,是一种开放标准(RFC 7519),用于安全地在双方之间传递信息,这篇文章主要介绍了golang 在Gin框架中使用JWT鉴权,需要的朋友可以参考下
    2024-07-07
  • Go批量操作excel导入到mongodb的技巧

    Go批量操作excel导入到mongodb的技巧

    这篇文章主要介绍了Go批量操作excel导入到mongo,包括选择命令行包,读取配置连接数据库的方法,本文示例代码相结合给大家介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • golang实现命令行程序的使用帮助功能

    golang实现命令行程序的使用帮助功能

    这篇文章介绍了golang实现命令行程序使用帮助的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • Golang sync.Pool的源码解析

    Golang sync.Pool的源码解析

    Pool是用于存放临时对象的集合,这些对象是为了后续的使用,以达到复用对象的效果,本文将详解解析sync.Pool 源码,需要的朋友可以参考下
    2023-05-05
  • Go语言关于几种深度拷贝(deepcopy)方法的性能对比

    Go语言关于几种深度拷贝(deepcopy)方法的性能对比

    这篇文章主要介绍了Go语言关于几种深度拷贝(deepcopy)方法的性能对比,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • go语言-在mac下brew升级golang

    go语言-在mac下brew升级golang

    这篇文章主要介绍了go语言-在mac下brew升级golang,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • 一文带你掌握Go语言中文件的写入操作

    一文带你掌握Go语言中文件的写入操作

    这篇文章主要和大家分享一下Go语言中文件的写入操作,文中的示例代码讲解详细,对我们学习Go语言有一定的帮助,需要的小伙伴可以参考一下
    2022-12-12
  • Golang时间及时间戳的获取转换超全面详细讲解

    Golang时间及时间戳的获取转换超全面详细讲解

    说实话,golang的时间转化还是很麻烦的,最起码比php麻烦很多,下面这篇文章主要给大家介绍了关于golang时间/时间戳的获取与转换的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • go:gin输出日志文件方式

    go:gin输出日志文件方式

    这篇文章主要介绍了go:gin输出日志文件方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01

最新评论