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语言通道之缓冲通道的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 在 Golang 中实现 Cache::remember 方法详解

    在 Golang 中实现 Cache::remember 方法详解

    这篇文章主要介绍了在 Golang 中实现 Cache::remember 方法详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • go语言实现屏幕截图的示例代码

    go语言实现屏幕截图的示例代码

    屏幕截图在很多地方都可以 用到,本文主要介绍了go语言实现屏幕截图的示例代码,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • golang定时器和超时的使用详解

    golang定时器和超时的使用详解

    这篇文章主要介绍了golang定时器和超时的使用详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go语言基础切片的创建及初始化示例详解

    Go语言基础切片的创建及初始化示例详解

    这篇文章主要为大家介绍了Go语言基础切片的创建及初始化示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2021-11-11
  • go语言 全局变量和局部变量实例

    go语言 全局变量和局部变量实例

    这篇文章主要介绍了go语言 全局变量和局部变量实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • go编译标签build tag注释里语法详解

    go编译标签build tag注释里语法详解

    这篇文章主要为大家介绍了go编译标签build tag注释里语法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Go基础教程系列之数据类型详细说明

    Go基础教程系列之数据类型详细说明

    这篇文章主要介绍了Go基础教程系列之数据类型详细说明,需要的朋友可以参考下
    2022-04-04
  • 再次探讨go实现无限 buffer 的 channel方法

    再次探讨go实现无限 buffer 的 channel方法

    我们知道go语言内置的channel缓冲大小是有上限的,那么我们自己如何实现一个无限 buffer 的 channel呢?今天通过本文给大家分享go实现无限 buffer 的 channel方法,感兴趣的朋友一起看看吧
    2021-06-06
  • Golang利用Template模板动态生成文本

    Golang利用Template模板动态生成文本

    Go语言中的Go Template是一种用于生成文本输出的简单而强大的模板引擎,它提供了一种灵活的方式来生成各种格式的文本,下面我们就来看看具体如何使用Template实现动态文本生成吧
    2023-09-09
  • 浅析Go常量为什么只支持基本数据类型

    浅析Go常量为什么只支持基本数据类型

    这篇文章主要来和大家一起讨论一下Golang中常量为什么只支持基本数据类型,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-09-09

最新评论