Go入门:并发的写法(通过生产消费者模型)

下面是代码示范;

实现背景: 去promotheus中获取不同的数据,并api接口返回数据。

我所考虑的问题:

  • error的处理
  • goroutine的控制
  • 代码的优雅和冗余性
  • 后续新需求的可拓展性

第一: error的处理
在这一段代码中, 需要对每一个调用service层可能出错的error进行捕捉,并返回给用户error信息.所以我用了 有缓冲的队列:errCh来接收error信息。

第二: goroutine的控制
控制并发数量,使用channel来控制并发数量,使用 sync.waitGroup来确保程序的阻塞。

func (w *dashboardWeb) GetViewData(ctx *gin.Context) (interface{}, error) {
    var (
        errCh     = make(chan error, 15)
        result    = model.DashboardViewResModel{}
        taskCount = 15
        ch        = make(chan func(), 4)
        wg        = sync.WaitGroup{}
    )

    StartTime := cast.ToInt64(ctx.Query("startTime"))
    EndTime := cast.ToInt64(ctx.Query("endTime"))
    Granularity := cast.ToInt(ctx.Query("granularity"))
    fns := []func(){
        func() {
            data, err := w.ListAz()
            if err != nil {
                errCh  0 {
        go func() {
            defer wg.Done()
            for fn := range ch {
                fn()
            }
        }()
        taskCount--
    }
    for _, fn := range fns {
        ch 

核心代码分析和引发的思考。

    for taskCount > 0 {
        go func() {
            defer wg.Done()
            for fn := range ch {
                fn()
            }
        }()
        taskCount--
    }
    for _, fn := range fns {
        ch 

上面的代码的写法我个人感觉比较优雅,它应用了golang的channel,使用了生产者消费者模型。

fns是一个匿名函数的列表, fn是一个一个的执行动作。

将每个执行动作(fn) 生产到我们定义的ch channel中即可

从上述的例子中,可以思考下,golang的生产者消费者模型?

生产者:发送数据端
消费者:接收数据端
为什么需要有缓冲区?
1.解耦(降低生产者与消费者之间的耦合度)当消费者发生变化时,不会直接影响到生产者。
2.并发。n个消费者可以先写入缓冲区,再由消费者读出。生产者和消费者数量不等时,能保持正常通信。
3.缓存数据:当生产者和消费者数据处理速度不一致时,暂存数据

image.png

例如:

package main

import (
    "fmt"
)

func producer(out chan
由于版权原因,本站共享资源只供云盘资源,版权均属于影片公司所有,请在下载后24小时删除,切勿用于商业用途。本站所有资源信息均从互联网搜索而来,本站不对显示的内容承担责任,如您认为本站页面信息侵犯了您的权益,请附上版权证明邮件并发送到[email protected]告知,我们会在收到邮件后72小时内删除。
想开点 » Go入门:并发的写法(通过生产消费者模型)