V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Aumujun
V2EX  ›  Go 编程语言

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

  •  
  •   Aumujun ·
    None · 2020-09-09 22:40:46 +08:00 · 2492 次点击
    这是一个创建于 1318 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码如下,目的是为了同时下载很多台交换机的配置,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()
    }
    
    11 条回复    2020-09-10 14:58:06 +08:00
    GGGG430
        1
    GGGG430  
       2020-09-09 23:02:30 +08:00   ❤️ 1
    外层的 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
        2
    Aumujun  
    OP
       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
        3
    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
        4
    iwdmb  
       2020-09-09 23:26:19 +08:00
    iwdmb
        5
    iwdmb  
       2020-09-09 23:27:14 +08:00   ❤️ 1
    上面兩個貼錯

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

    @GGGG430 两位的思路大体差不多,拿过来稍微改改就可以了。
    Aumujun
        7
    Aumujun  
    OP
       2020-09-09 23:34:53 +08:00
    非常感谢,优化成这种程度我已经满足了,感谢两位大哥的指点
    heimeil
        8
    heimeil  
       2020-09-10 02:04:52 +08:00   ❤️ 1
    zarte
        9
    zarte  
       2020-09-10 09:58:32 +08:00   ❤️ 1
    我觉得可以加下限制协程数。
    situs
        10
    situs  
       2020-09-10 12:18:47 +08:00   ❤️ 1
    你的 Done()应该用 defer,你现在是顺序执行的,如果上面 err 了,你这协程 done 不了了
    dafsic
        11
    dafsic  
       2020-09-10 14:58:06 +08:00   ❤️ 1
    你这个是多协程处理同样的任务的,没有最多协程的数的限制。https://github.com/90634/gotaskengine,我线上环境用的,多协程处理多任务的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2973 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 03:02 · PVG 11:02 · LAX 20:02 · JFK 23:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.