[不懂就问] 请问这段 Golang Go语言代码该如何优化

发布于 1周前 作者 yibo5220 来自 Go语言

[不懂就问] 请问这段 Golang Go语言代码该如何优化

代码如下,目的是为了同时下载很多台交换机的配置,sws 里有多组业务的交换机,每个业务的每一台配置的下载我都要同时进行,下面的代码是我拍脑袋写下来的,目的达到了,但怎么看都不顺眼,我的 go 水平目前实在有限,求助各位指导一下。

func (s *swbka) downloadSwitchCfg(sws map[string]mulparam) {
	wgp := sync.WaitGroup{}
	wgp.Add(len(sws))
	for secN, mulP := range sws {
		go func(secName string, mulP mulparam) {

			if _, err := os.Stat(secName); os.IsNotExist(err) {
				err := os.Mkdir(secName, 0644)
				if err != nil {
					logrus.Fatal(err)
				}
			}
			wg := sync.WaitGroup{}
			wg.Add(len(mulP.profiles))
			for _, profile := range mulP.profiles {
				go func(sn string, pf param) {
					err := s.downloadFile(sn, pf)
					if err != nil {
						logrus.Errorln(err)
					}
					wg.Done()
				}(secName, profile)
			}
			wg.Wait()
			wgp.Done()
		}(secN, mulP)
	}
	wgp.Wait()
}

更多关于[不懂就问] 请问这段 Golang Go语言代码该如何优化的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

12 回复

外层的 WaitGroup 可以理解为进程等待, 里层的 WaitGroup+go func 感觉没必要;
或者这样简化一下
<br> func (s *swbka) downloadSwitchCfg(sws map[string]mulparam) {<br> wgp := sync.WaitGroup{}<br> for secN, mulP := range sws {<br> if _, err := os.Stat(secName); os.IsNotExist(err) {<br> if err := os.Mkdir(secName, 0644); err != nil {<br> logrus.Fatal(err)<br> continue<br> }<br> }<br> wgp.Add(1)<br> for _, profile := range mulP.profiles {<br> go func(sn string, pf param, wg *sync.WaitGroup) {<br> defer func() {<br> wg.Done()<br> }()<br> err := s.downloadFile(sn, pf)<br> if err != nil {<br> logrus.Errorln(err)<br> }<br> }(secName, profile, &amp;wgp)<br> }<br> }<br> wgp.Wait()<br> }<br>

更多关于[不懂就问] 请问这段 Golang Go语言代码该如何优化的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你这个看起来确实比我原来那个强太多了,发帖之后思考了一下,改成了下面这样

golang<br>func downloadFunc(s *swbka, wg *sync.WaitGroup, secName string, mulP mulparam) {<br> if _, err := os.Stat(secName); os.IsNotExist(err) {<br> err := os.Mkdir(secName, 0644)<br> if err != nil {<br> logrus.Fatal(err)<br> }<br> }<br> for _, profile := range mulP.profiles {<br> go func(sn string, pf param) {<br> // err := s.downloadFile(sn, pf)<br> err := s.downloadFileMock(sn, pf)<br> wg.Done()<br> if err != nil {<br> logrus.Errorln(err)<br> }<br> }(secName, profile)<br> }<br>}<br><br>func (s *swbka) downloadSwitchCfg(sws map[string]mulparam) {<br> wg := sync.WaitGroup{}<br> // wg.Add(len(sws))<br> for secN, mulP := range sws {<br> wg.Add(len(mulP.profiles))<br> go downloadFunc(s, &amp;wg, secN, mulP)<br> }<br> wg.Wait()<br>}<br>

不过看了你的回复后,感觉获得了新的启示

<br>func (s *swbka) downloadSwitchCfg(sws map[string]mulparam) {<br> wgp := sync.WaitGroup{}<br> wgp.Add(len(sws))<br><br> for secName, mulP := range sws {<br> go func(secName string, mulP mulparam) {<br> if _, err := os.Stat(secName); os.IsNotExist(err) {<br> err := os.Mkdir(secName, 0644)<br> if err != nil {<br> logrus.Fatal(err)<br> }<br> }<br><br> wg := sync.WaitGroup{}<br> wg.Add(len(mulP.profiles))<br> for _, profile := range mulP.profiles {<br> go func(sn string, pf param) {<br> err := s.downloadFile(sn, pf)<br> if err != nil {<br> logrus.Errorln(err)<br> }<br> wg.Done()<br> }(secName, profile)<br> }<br><br> wg.Wait()<br> wgp.Done()<br> }(secN, mulP)<br> }<br> wgp.Wait()<br>}<br>

上面兩個貼錯

這個試試看: https://play.golang.com/p/3WyN4JrDmbQ

感谢大哥的回复,这个版本确实好看很多,现在已经用上了。

两位的思路大体差不多,拿过来稍微改改就可以了。

非常感谢,优化成这种程度我已经满足了,感谢两位大哥的指点

我觉得可以加下限制协程数。

你的 Done()应该用 defer,你现在是顺序执行的,如果上面 err 了,你这协程 done 不了了

你这个是多协程处理同样的任务的,没有最多协程的数的限制。https://github.com/90634/gotaskengine,我线上环境用的,多协程处理多任务的。

当然,很高兴帮助你优化Golang代码。不过,由于你没有提供具体的代码片段,我将给出一些通用的优化建议,这些建议通常适用于大多数Golang程序:

  1. 使用高效的数据结构:根据具体需求选择合适的数据结构,比如map、slice或channel,避免不必要的内存分配和复制。

  2. 并发编程:利用Goroutines和channels实现并发,但要小心避免数据竞争和死锁。使用sync包中的工具(如sync.Mutexsync.WaitGroup)来管理并发访问。

  3. 避免不必要的锁:尽量减少锁的粒度,使用局部变量代替全局变量,以减少锁的竞争。

  4. 错误处理:使用简洁的错误处理策略,避免过多的嵌套。考虑使用errors.Iserrors.As来处理特定错误类型。

  5. 代码复用:将重复的代码封装成函数或方法,提高代码的可读性和可维护性。

  6. 性能分析:使用Go的内置工具(如go tool pprof)进行性能分析,找出瓶颈并优化。

  7. 代码审查:定期进行代码审查,不仅可以发现潜在的问题,还能提高团队的整体代码质量。

如果你能提供具体的代码片段,我可以给出更具体的优化建议。希望这些建议对你有所帮助!

回到顶部