iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >如何解决Golang中使用WaitGroup的问题
  • 273
分享到

如何解决Golang中使用WaitGroup的问题

2023-06-14 20:06:49 273人浏览 安东尼
摘要

这篇文章主要介绍了如何解决golang中使用WaitGroup的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Golang的优点golang是一种编译语言,可以将代码编译

这篇文章主要介绍了如何解决golang中使用WaitGroup的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

Golang的优点

golang是一种编译语言,可以将代码编译为机器代码,编译后的二进制文件可以直接部署到目标机器而无需额外的依赖,所以golang的性能优于其他的解释性语言,且可以在golang中使用goroutine来实现并发性,它提供了一个非常优雅的goroutine调度程序系统,可以很容易地生成数百万个goroutine。

sync.WaitGroup对于Golang开发者来说并不陌生,其经常作为多协程之间同步的一种机制。用好它势必会让你事半功倍,但是一旦错用将引发问题。

关于WaitGroup的使用网上有很多例子,在此就不做介绍了,我想说的是我在项目中使用WaitGroup遇到的坑。

在项目中,因为服务器有同步需求, 所以直接使用了WaitGroup,但是未考虑使用场景,结果在项目上线之后,高峰期的时候客户端经常出现卡顿,经过多方查找,才发现如果使用WaitGroup的时候,未启动单独的goroutine,那么极有可能造成主线程的阻塞

所以我做了下面的测试(测试中,我把WaitGroup置于协程内):

import ( "fmt" "sync" "time") func main() {    fmt.Println("main-1") testW() fmt.Println("main-2") time.Sleep(time.Duration(15) * time.Second) } func testW() { fmt.Println("testW-1") go func() {  var wg sync.WaitGroup  fmt.Println("testW-2")  testW1(&wg)  fmt.Println("testW-5")  wg.Wait()  fmt.Println("testW-6") }()} func testW1(wg *sync.WaitGroup) { wg.Add(1) fmt.Println("testW-3") time.AfterFunc(time.Second*5, func() {  wg.Done() }) fmt.Println("testW-4") }

输出为:

main-1

testchan-1

main-2

testchan-2

testchan-3

testchan-4

testchan-5

// 过5秒

testchan-6

总结

将WaitGroup用于goroutine内,不会导致主线程的阻塞,同样可以实现同步的效果。

补充:WaitGroup的简单用法(等待组)

你品一下人家这名字,等待组。等待什么,等待goroutine完成啊。有些时候,我们启动多个goroutine去执行任务,我举个例子

listip := []string{"10.0.9.11","10.0.9.22","10.0.9.33"}for _, ip := range(listip) {    //假设我们执行一个ping ip 的逻辑    go PingIPWork(ip)}

我这里执行了一个多ip去ping的逻辑,一般这种时候,你要是执行一波,人家肯定毛都不会返回给你,为什么?因为人家主线程直接就退出了,还是那句话,你又没告诉人家主线程要等这ip全部都ping 完,所以你必须要加个等待,等着Goroutine完成,这里我再举一个网上的例子

package mainimport (    "fmt")func main() {    go func() {        fmt.Println("Goroutine 1")    }()    go func() {        fmt.Println("Goroutine 2")    }()    //来个睡眠,等Goroutine结束    time.Sleep(time.Second * 1)}

看到了么,加了一个sleep,用sleep去等着Goroutine跑完,上面我举的那个例子也可以这么来

listip := []string{"10.0.9.11","10.0.9.22","10.0.9.33"}for _, ip := range(listip) {    //假设我们执行一个ping ip 的逻辑    go PingIPWork(ip)}time.Sleep(time.Second * 1)

加个sleep可以等待完成,但是万一啊,Goroutine有的跑的快,有的慢,你那sleep就一秒,要是有的Goroutine没跑完不就白瞎了吗,所以咱们需要一个机制,这个机制可以帮助咱们去管理Goroutine,让我们知道Goroutine这东西什么时候停,什么时候完成。

所以,WaitGroup这个东西,就可以帮助我们解决这个问题,还是老样子,我举一个简单的例子来说明我的想法。

package mainimport (    "fmt" "sync")func PingIPWork(ip string) { fmt.Println(ip)}func main() {    //定义一个等待阿祖 var wg sync.WaitGroup wg.Add(3) // 因为有3个Ip,咱们定义三个动作,所以来三个计数 listip := []string{"10.0.9.11","10.0.9.22","10.0.9.33"} for _, ip := range(listip) {  //假设我们执行一个ping ip 的逻辑  go func(ip string) {            //执行一个work            PingIPWork(ip)            //操作完成之后,done一个计数,也就是3-1   wg.Done()  }(ip) }    //等待 wg.Wait() // 等待,直到计数为0}

这里我举了一个简单的例子,其实wg的用法较为简单,在这个例子里面我们用到了

wg.wait等待Goroutine结束之后退出主进程wg.Add添加Goroutine,其实你可以把它想成,可添加的最大Goroutine数wg.Done想象成销毁参数,当Goroutine结束之后调用,意思就是,你没了,我减1

WaitGroup的其他注意事项

将Wg作为参数进行传递的时候,需要使用指针

有些时候,咱们不想写的这么麻烦,就寻思怎么才能简单一点,或者可变性稍微强一点,有些时候我们要把wg最为参数,在函数内部调用,我们该怎么写呢?

package mainimport ( "fmt" "sync")func PingIPWork(ip string, wg *sync.WaitGroup) { fmt.Println(ip) wg.Done()}func main() { var wg sync.WaitGroup wg.Add(3) // 因为有两个动作,所以增加2个计数 listip := []string{"10.0.9.11","10.0.9.22","10.0.9.33"} for _, ip := range(listip) {  //假设我们执行一个ping ip 的逻辑  go PingIPWork(ip, &wg)  } wg.Wait() // 等待,直到计数为0}

看到了么,如果你把Wg作为参数进行传递,你得要用指针的形式传值,否则就会死!!!!!!!!

Wg.Add的数值不能为负

wg.Add()的数值必须为正数,如果为负数,将会抛出异常。

panic: sync: negative WaitGroup countergoroutine 1 [running]:sync.(*WaitGroup).Add(0xc042008230, 0xffffffffffffff9c)    D:/Go/src/sync/waitgroup.go:75 +0x1d0main.main()    D:/code/go/src/test-src/2-Package/sync/waitgroup/main.go:10 +0x54

感谢你能够认真阅读完这篇文章,希望小编分享的“如何解决Golang中使用WaitGroup的问题”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网GO频道,更多相关知识等着你来学习!

您可能感兴趣的文档:

--结束END--

本文标题: 如何解决Golang中使用WaitGroup的问题

本文链接: https://www.lsjlt.com/news/275059.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何解决Golang中使用WaitGroup的问题
    这篇文章主要介绍了如何解决Golang中使用WaitGroup的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。golang的优点golang是一种编译语言,可以将代码编译...
    99+
    2023-06-14
  • 解决Golang 中使用WaitGroup的那点坑
    sync.WaitGroup对于Golang开发者来说并不陌生,其经常作为多协程之间同步的一种机制。用好它势必会让你事半功倍,但是一旦错用将引发问题。 关于WaitGroup的使用网...
    99+
    2024-04-02
  • 如何使用泛型解决golang中常见问题?
    go 中泛型可解决常见痛点:类型转换:使用泛型函数简化不同类型的转换。数据结构创建:使用泛型类型简化通用数据结构的创建。函数传递:使用泛型函数声明允许传递各种类型的参数。实战案例:通过类...
    99+
    2024-05-04
    golang 泛型 编译错误 键值对
  • 如何解决golang中关闭chan的问题
    学习Golang要努力,但是不要急!今天的这篇文章《如何解决golang中关闭chan的问题》将会介绍到等等知识点,如果你想深入学习Golang,可以关注我!我会持续更新相关文章的,希望对大家都能有...
    99+
    2024-04-04
  • 如何使用泛型解决golang中数据处理问题
    go 中的泛型允许创建处理各种类型数据的函数和类型,从而简化数据处理。它通过类型参数实现,这些参数可以在函数和类型中使用,强制执行类型安全并提高代码重用性、可读性和可维护性。 如何使用...
    99+
    2024-05-04
    golang 泛型 代码可读性
  • 如何使用泛型解决golang中并发编程问题
    使用泛型解决 golang 中的并发问题。泛型允许在不指定类型的情况下定义函数和结构,从而创建线程安全的数据结构。例如:定义一个泛型队列 queue[t],其中 t 表示元素类型。使用 ...
    99+
    2024-05-03
    golang 泛型 并发访问
  • 在golang中使用Sync.WaitGroup解决等待的问题
    面对goroutine我们都需要等待它完成交给它的事情,等待它计算完成或是执行完毕,所以不得不在程序需要等待的地方使用time.Sleep()来睡眠一段时间,等待其他goroytin...
    99+
    2024-04-02
  • 如何解决vue中less的使用问题
    小编给大家分享一下如何解决vue中less的使用问题,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!安装less依赖:npm install less less-loader --save修改webpack.base.con...
    99+
    2023-06-25
  • 如何解决MySQL使用中遇到的问题
    这篇文章给大家分享的是有关如何解决MySQL使用中遇到的问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。sql_mode=only_full_group_by引起group b...
    99+
    2024-04-02
  • 如何使用github解决问题
    这篇“如何使用github解决问题”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何使用github解决问题”文章吧。一、G...
    99+
    2023-07-06
  • 如何解决此问题:恐慌:同步:负数 WaitGroup 计数器
    问题内容 一次又一次运行后,我有时会遇到这个问题。我知道这与计数器相关。当调用sync.waitgroup的done()方法的次数多于调用add()方法的次数时,它将抛出此错误。 如何...
    99+
    2024-02-05
  • golang中包无法引入问题如何解决
    这篇文章主要讲解了“golang中包无法引入问题如何解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang中包无法引入问题如何解决”吧!问题背景开发环境区分不同网段,同一个程序引入到...
    99+
    2023-07-05
  • 如何解决golang中cat输出乱码问题
    这篇文章主要介绍了如何解决golang中cat输出乱码问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。今天遇到个问题,排查日志文件返回的结果集,使用如命令: ca...
    99+
    2023-06-14
  • 如何使用TRACERT解决Windows中的TCP/IP问题
    要使用TRACERT解决Windows中的TCP/IP问题,您可以按照以下步骤操作:1. 打开命令提示符:点击开始菜单,搜索"命令提...
    99+
    2023-09-13
    Windows
  • Golang中importcyclenotallowed问题的解决方法
    目录1.问题现象2.问题分析3.解决问题思路4.如何破除依赖5.问题回顾1.问题现象 go编译的时候报错import cycle not allowed cycle意思很简单就是循...
    99+
    2024-04-02
  • Golang共享变量如何解决问题
    目录1. 什么是竞态 2. 如何消除竞态 3. Go 提供的并发工具 3.1 互斥锁 3.2 读写互斥锁 3.3 Once 3.4 竞态检测器 4. 小结 在之前的文章中,我们详细说...
    99+
    2024-04-02
  • 如何解决golang在import包报错的问题
    这篇文章主要介绍了如何解决golang在import包报错的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。什么是golanggolang 是Google开发的一种静态强类...
    99+
    2023-06-14
  • 如何使用Golang继承方法解决问题和应用范例
    Golang继承方法的优势和应用场景 在Go语言中,虽然没有传统意义上的类的概念,但是通过结构体的嵌套和方法的继承,我们可以实现类似其他面向对象语言中的继承机制。本文将介绍Golang继承方法的优势和应用场景...
    99+
    2024-01-20
    方法 应用场景 继承
  • 如何解决MySQL使用中文乱码问题
    这篇文章给大家分享的是有关如何解决MySQL使用中文乱码问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1、中文乱码1.1、中文乱码 create table user(name&...
    99+
    2023-06-28
  • Golang开发中如何解决共享变量问题
    目录1、什么是竞态2、如何消除竞态3、Go 提供的并发工具3.1 互斥锁3.2 读写互斥锁3.3 Once3.4 竞态检测器4、小结Go 语言中 goroutine + channe...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作