当前位置: 首页 > article >正文

Go 语言并发实战:利用协程处理多个接口进行数据融合

高效地处理多个数据源并将其整合为有意义的结果是开发中一项重要的任务。Go 语言,以其强大的并发特性,为我们提供了优雅而高效的解决方案。那么我们探讨一下如何利用 Go 语言的协程,同时调用多个接口获取数据,并将这些数据无缝地合并为一个完整的数据集。

先假定一个场景:现有一需求,需要请求n个接口(暂定为3个)获取接口数据,然后对数据进行二次处理并返回。

按照过往的经验,我们会依次请求接口拿到数据暂存,最后对数据进行包装处理,这种自上而下的处理方式其实并无不妥,现在想要提高下效率,利用牺牲cpu资源来换取查询性能。

  1. 先模拟创建几个接口,分别返回(k1,v1)、(k2,v2)、(k3,v4):

    // 模拟接口A
    func getDataFromA() map[string]interface{} {
        return map[string]interface{}{
            "key1": "value1",
        }
    }
    
    // 模拟接口B
    func getDataFromB() map[string]interface{} {
        return map[string]interface{}{
            "key2": "value2",
        }
    }
    
    // 模拟接口C
    func getDataFromC() map[string]interface{} {
        return map[string]interface{}{
            "key3": "value3",
        }
    }
    
  2. 开启协程分别请求上述接口:
    首先得思考一个问题,协程执行不保证顺序,请求到的数据应该怎么保存?怎么判断全部协程都执行完毕?怎么拿到全部的数据?

    • 上述接口定义中返回的数据均是 map,那么我完全可以用map来保存数据,所以我定义方法就可以这么定义:

      func getAllData() map[string]interface{} {
          return nil    // 暂时先不做处理
      }
      
    • 为了防止主协程先于其他执行结束,需要引入 sync.WaitGroup 包控制;所有协程返回的数据,可以用通道来暂存,make 一个容量为 3 的 Channel

      func getAllData() map[string]interface{} {
          var wg sync.WaitGroup
          resultChan := make(chan map[string]interface{}, 3)
          return nil    // 暂时先不做处理
      }
      
    • 接下来就可以开启协程去调用:

      func getAllData() map[string]interface{} {
      	var wg sync.WaitGroup
      	resultChan := make(chan map[string]interface{}, 3)
      	
      	wg.Add(3)
      	go func() {
      		defer wg.Done()
      		resultChan <- getDataFromA()
      	}()
      
      	go func() {
      		defer wg.Done()
      		resultChan <- getDataFromB()
      	}()
      
      	go func() {
      		defer wg.Done()
      		resultChan <- getDataFromC()
      	}()
      
      	wg.Wait()
      	close(resultChan)
      	return nil // 暂时先不做处理
      }
      
    • 最后可以对数据做个简单处理,封装成一个大map返回,实际业务当然按需处理:

      newMap := make(map[string]interface{})
      	for res := range resultChan {
      		for k, v := range res {
      			newMap [k] = v
      	}
      }
      
      return newMap
      
  3. 执行验证返回结果:

    func main() {
    	newMap := getAllData()
    	fmt.Println(newMap)
    }
    
    [Running] go run "main.go"
    map[key1:value1 key2:value2 key3:value3]
    


http://www.kler.cn/a/448517.html

相关文章:

  • MySQL表名传参SP
  • 【JetPack】WorkManager笔记
  • druid与pgsql结合踩坑记
  • PostgreSQL标识符长度限制不能超过63字节
  • Python中的上下文管理器:从资源管理到自定义实现
  • bestphp‘s revenge
  • 常耀斌:深度学习和大模型原理与实战(深度好文)
  • 【漫话机器学习系列】012.深度学习(Deep Learning)基础
  • Webpack的打包过程/打包原理/构建流程?
  • Unity Shader学习日记 part 1 基础知识
  • 广义正态分布优化算法(GNDO)Generalized Normal Distribution Optimization
  • LeetCode 力扣 热题 100道(二十)三数之和(C++)
  • Unity 6 Preview(预览版)新增功能
  • windows下srs流媒体服务器使用ffmpeg推流
  • 鸿蒙项目云捐助第十八讲云捐助我的页面下半部分的实现
  • c# iis 解决跨域问题
  • 对象克隆与单例模式的实现
  • 硬件工程师面试题 11-20
  • 【WRF教程第3.6期】预处理系统 WPS 详解:以4.5版本为例
  • 使用插件时要注意
  • C语言——实现字符分类统计
  • Linux 使用的小细节
  • Webpack简单介绍及安装
  • 深度学习试题及答案解析(二)
  • 【ETCD】【实操篇(三)】【ETCDCTL】如何向集群中写入数据
  • LeetCode 583. 两个字符串的删除操作 java题解