[不懂就问] 请问这段 go 代码该如何优化

2020-09-09 22:40:46 +08:00
 Aumujun

代码如下,目的是为了同时下载很多台交换机的配置,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()
}
2500 次点击
所在节点    Go 编程语言
11 条回复
GGGG430
2020-09-09 23:02:30 +08:00
外层的 WaitGroup 可以理解为进程等待, 里层的 WaitGroup+go func 感觉没必要;
或者这样简化一下
```
func (s *swbka) downloadSwitchCfg(sws map[string]mulparam) {
wgp := sync.WaitGroup{}
for secN, mulP := range sws {
if _, err := os.Stat(secName); os.IsNotExist(err) {
if err := os.Mkdir(secName, 0644); err != nil {
logrus.Fatal(err)
continue
}
}
wgp.Add(1)
for _, profile := range mulP.profiles {
go func(sn string, pf param, wg *sync.WaitGroup) {
defer func() {
wg.Done()
}()
err := s.downloadFile(sn, pf)
if err != nil {
logrus.Errorln(err)
}
}(secName, profile, &wgp)
}
}
wgp.Wait()
}
```
Aumujun
2020-09-09 23:11:43 +08:00
@GGGG430 你这个看起来确实比我原来那个强太多了,发帖之后思考了一下,改成了下面这样

```golang
func downloadFunc(s *swbka, wg *sync.WaitGroup, secName string, mulP mulparam) {
if _, err := os.Stat(secName); os.IsNotExist(err) {
err := os.Mkdir(secName, 0644)
if err != nil {
logrus.Fatal(err)
}
}
for _, profile := range mulP.profiles {
go func(sn string, pf param) {
// err := s.downloadFile(sn, pf)
err := s.downloadFileMock(sn, pf)
wg.Done()
if err != nil {
logrus.Errorln(err)
}
}(secName, profile)
}
}

func (s *swbka) downloadSwitchCfg(sws map[string]mulparam) {
wg := sync.WaitGroup{}
// wg.Add(len(sws))
for secN, mulP := range sws {
wg.Add(len(mulP.profiles))
go downloadFunc(s, &wg, secN, mulP)
}
wg.Wait()
}
```

不过看了你的回复后,感觉获得了新的启示
iwdmb
2020-09-09 23:24:29 +08:00
```
func (s *swbka) downloadSwitchCfg(sws map[string]mulparam) {
wgp := sync.WaitGroup{}
wgp.Add(len(sws))

for secName, 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()
}
```
iwdmb
2020-09-09 23:26:19 +08:00
iwdmb
2020-09-09 23:27:14 +08:00
上面兩個貼錯

這個試試看: https://play.golang.com/p/3WyN4JrDmbQ
Aumujun
2020-09-09 23:34:05 +08:00
@iwdmb 感谢大哥的回复,这个版本确实好看很多,现在已经用上了。

@GGGG430 两位的思路大体差不多,拿过来稍微改改就可以了。
Aumujun
2020-09-09 23:34:53 +08:00
非常感谢,优化成这种程度我已经满足了,感谢两位大哥的指点
heimeil
2020-09-10 02:04:52 +08:00
zarte
2020-09-10 09:58:32 +08:00
我觉得可以加下限制协程数。
situs
2020-09-10 12:18:47 +08:00
你的 Done()应该用 defer,你现在是顺序执行的,如果上面 err 了,你这协程 done 不了了
dafsic
2020-09-10 14:58:06 +08:00
你这个是多协程处理同样的任务的,没有最多协程的数的限制。https://github.com/90634/gotaskengine,我线上环境用的,多协程处理多任务的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/705630

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX