[不懂就问] 请问这段 Golang 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
外层的 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, &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, &wg, secN, mulP)<br> }<br> wg.Wait()<br>}<br>
不过看了你的回复后,感觉获得了新的启示
上面兩個貼錯
這個試試看: https://play.golang.com/p/3WyN4JrDmbQ
感谢大哥的回复,这个版本确实好看很多,现在已经用上了。
两位的思路大体差不多,拿过来稍微改改就可以了。
非常感谢,优化成这种程度我已经满足了,感谢两位大哥的指点
我觉得可以加下限制协程数。
你的 Done()应该用 defer,你现在是顺序执行的,如果上面 err 了,你这协程 done 不了了
你这个是多协程处理同样的任务的,没有最多协程的数的限制。https://github.com/90634/gotaskengine,我线上环境用的,多协程处理多任务的。
当然,很高兴帮助你优化Golang代码。不过,由于你没有提供具体的代码片段,我将给出一些通用的优化建议,这些建议通常适用于大多数Golang程序:
-
使用高效的数据结构:根据具体需求选择合适的数据结构,比如map、slice或channel,避免不必要的内存分配和复制。
-
并发编程:利用Goroutines和channels实现并发,但要小心避免数据竞争和死锁。使用
sync
包中的工具(如sync.Mutex
、sync.WaitGroup
)来管理并发访问。 -
避免不必要的锁:尽量减少锁的粒度,使用局部变量代替全局变量,以减少锁的竞争。
-
错误处理:使用简洁的错误处理策略,避免过多的嵌套。考虑使用
errors.Is
和errors.As
来处理特定错误类型。 -
代码复用:将重复的代码封装成函数或方法,提高代码的可读性和可维护性。
-
性能分析:使用Go的内置工具(如
go tool pprof
)进行性能分析,找出瓶颈并优化。 -
代码审查:定期进行代码审查,不仅可以发现潜在的问题,还能提高团队的整体代码质量。
如果你能提供具体的代码片段,我可以给出更具体的优化建议。希望这些建议对你有所帮助!