目录

发送给独立的goroutine处理程序

在当前函数中聚合返回


执行go协程时, 是没有返回值的, 这时候需要用到go语言中特色的channel来获取到返回值.

通过channel拿到返回值有两种处理形式,

一种形式是具有go风格特色的, 即发送给一个for channelselect channel的独立goroutine中, 由该独立的goroutine来处理函数的返回值.

还有一种传统的做法, 就是将所有goroutine的返回值都集中到当前函数, 然后统一返回给调用函数.

发送给独立的goroutine处理程序

package mainimport ("fmt""sync""time"
)var responseChannel = make(chan string, 15)func httpGet(url int, limiter chan bool, wg *sync.WaitGroup) {// 函数执行完毕时 计数器-1defer wg.Done()fmt.Println("http get:", url)responseChannel <- fmt.Sprintf("Hello Go %d", url)// 释放一个坑位<- limiter
}func ResponseController() {for rc := range responseChannel {fmt.Println("response: ", rc)}
}func main() {// 启动接收response的控制器go ResponseController()wg := &sync.WaitGroup{}// 控制并发数为10limiter := make(chan bool, 20)for i := 0; i < 99; i++ {// 计数器+1wg.Add(1)limiter <- truego httpGet(i, limiter, wg)}// 等待所以协程执行完毕wg.Wait() // 当计数器为0时, 不再阻塞fmt.Println("所有协程已执行完毕")
}

这种具有Go语言特色的处理方式的关键在于, 你需要预先创建一个用于处理返回值的公共管道. 然后定义一个一直在读取该管道的函数, 该函数需要预先以单独的goroutine形式启动.

最后当执行到并发任务时, 每个并发任务得到结果后, 都会将结果通过管道传递到之前预先启动的goroutine中.

在当前函数中聚合返回

package mainimport ("fmt""sync"
)func httpGet(url int,response chan string, limiter chan bool, wg *sync.WaitGroup) {// 函数执行完毕时 计数器-1defer wg.Done()// 将拿到的结果, 发送到参数中传递过来的channel中response <- fmt.Sprintf("http get: %d", url)// 释放一个坑位<- limiter
}// 将所有的返回结果, 以 []string 的形式返回
func collect(urls []int) []string {var result []stringwg := &sync.WaitGroup{}// 控制并发数为10limiter := make(chan bool, 5)defer close(limiter)// 函数内的局部变量channel, 专门用来接收函数内所有goroutine的结果responseChannel := make(chan string, 20)// 为读取结果控制器创建新的WaitGroup, 需要保证控制器内的所有值都已经正确处理完毕, 才能结束wgResponse := &sync.WaitGroup{}// 启动读取结果的控制器go func() {// wgResponse计数器+1wgResponse.Add(1)// 读取结果for response :=  range responseChannel {// 处理结果result = append(result, response)}// 当 responseChannel被关闭时且channel中所有的值都已经被处理完毕后, 将执行到这一行wgResponse.Done()}()for _, url := range urls {// 计数器+1wg.Add(1)limiter <- true// 这里在启动goroutine时, 将用来收集结果的局部变量channel也传递进去go httpGet(url,responseChannel, limiter, wg)}// 等待所以协程执行完毕wg.Wait() // 当计数器为0时, 不再阻塞fmt.Println("所有协程已执行完毕")// 关闭接收结果channelclose(responseChannel)// 等待wgResponse的计数器归零wgResponse.Wait()// 返回聚合后结果return result
}func main() {urls := []int{1,2,3,4,5,6,7,8,9,10}result := collect(urls)fmt.Println(result)
}

golang goroutine 得到返回值相关推荐

  1. Go语言自学系列 | golang函数的返回值

    视频来源:B站<golang入门到项目实战 [2021最新Go语言教程,没有废话,纯干货!持续更新中...]> 一边学习一边整理老师的课程内容及试验笔记,并与大家分享,侵权即删,谢谢支持! ...

  2. golang 返回值报错 cannot use nil as type string in return argument

    在刚刚开始使用golang写代码的时候,经常会放错.给一个变量放回一个nil,这个通常编译的时候不会报错,但是运行是时候会报cannot use nil as type string in retur ...

  3. golang 函数一 (定义、参数、返回值)

    对于GoLang函数的定义或者说理解: 函数是结构化编程中最小的模块单元,日常开发过程中,将复杂的算法过程分解为若干个小任务(代码块),使程序的结构性更清晰,程序可读性提升,易于后期维护和让别人读懂你 ...

  4. golang函数——可以为类型(包括内置数据类型)定义函数,类似类方法,同时支持多返回值...

    不可或缺的函数,在Go中定义函数的方式如下: func (p myType ) funcName ( a, b int , c string ) ( r , s int ) {return } 通过函 ...

  5. [Golang]一道考察defer与命名返回值的题目

    题目 输出: 4 1 3 解释 当函数有可命名结果形参时,结果形参的初始值被设置为零值,函数的return语句会设置结果形参的值 当函数有可命名结果形参时,defer函数是可以修改它,然后再将它的值返 ...

  6. golang函数:命名返回值代码示例

    http://tour.studygolang.com/basics/7 命名返回值 Go 的返回值可被命名,它们会被视作定义在函数顶部的变量. 返回值的名称应当具有一定的意义,它可以作为文档使用. ...

  7. golang函数调用机制:多返回值,_返回值忽略

    通俗易懂的方式的理解 函数-调用过程 介绍:为了让大家更好的理解函数调用过程, 看两个案例,并画出示意图,这个很重要. 传入一个数+1 对上图说明 : (1) 在调用一个函数时,会给该函数分配一个新的 ...

  8. 392. 判断子序列 golang 关于布尔类型返回值判断的思考

    Me 1.取每一个字符串的字符进行比较. 2.相等就i++,j++,不相等就j++ 3.如果s空了,那么就是true.如果t字符串空了那么...有很多种情况.所以这个解法不好. 但是如果把返回条件设置 ...

  9. golang 返回值问题

    当return后面为空是,函数声明时的func Auth (a int) 会把 a 作为返回值, 当 return b不为空时,会把 return 后面的b值作为返回值 return 不跟变量可以自动 ...

最新文章

  1. R多变量正态性检验(Multivariate Normality Tests)
  2. Redhat 7使用CentOS 7的Yum网络源
  3. 成功解决SyntaxError: import * only allowed at module level
  4. ExtJs学习笔记(21)-使用XTemplate结合WCF显示数据
  5. TCP/IP:IP多播选路
  6. Hbase Solr 二级索引,更新数据部分字段丢失问题
  7. jdk 安装_Linux安装JDK操作手册
  8. 疑似一加7 Pro 5G版通过3C认证:配备30W快充头
  9. 毕啸南专栏 | 专访云迹科技CEO支涛:人类可能会变成半机器人
  10. 架构再升级,云原生技术助力MySQL性能飙升40%
  11. iredmail mysql 配置_CentOS下iRedMail安装配置
  12. 淘宝自动查券找券返利机器人搭建教程
  13. cad文字递增快捷键_Auto CAD2014数字递增复制快捷键是什么呢?
  14. 金蝶KIS保存记账凭证的时候提示“在清除未下设辅助账的科目所在的会计分录中的核算项目代码时出现冲突或错误,凭证还没有被保存,请您稍后重试。”错误
  15. 独家访谈N位品牌操盘手:深度揭秘品牌自播方法论
  16. Ubuntu18.04 编译报错 `No package ‘orocos-bfl‘ found` 的解决方法
  17. 企业数字化转型-从企业IT部门和CIO的数字化思想开始
  18. Python将图片写到音频频谱
  19. char类型与varchar类型的区别
  20. 干货!#黑客大会PPT资源#,快来领取吧!

热门文章

  1. 人生致命的8个经典问题
  2. groovy 慢_groovy优化
  3. 32位数据源中没有mysql_如何在.NET中连接到MySQL数据库
  4. NetDevOps — SNMP 协议
  5. AWS — AWS 上的 5G 专网部署模式
  6. 5G 行业专网 — 公有云上的 5G 专网
  7. Kubernetes — HOST-DEVICE CNI
  8. Keil编译Entry point (0x00100000) lies outside the image.错误
  9. 电路设计中三极管和MOS管做开关用时的区别
  10. EF架构~为分组添加位运算聚合方法