У меня есть код ниже, который извлекает список URL-адресов, а затем условно загружает файл и сохраняет его в файловой системе. Файлы выбираются одновременно, и главный goroutine ждет всех файлов, которые будут извлечены. Но программа никогда не выходит (и ошибок нет) после завершения всех запросов.golang sync.WaitGroup никогда не завершает
То, что я думаю, что происходит, что-то количество их процедур в WaitGroup
либо увеличивается слишком много, чтобы начать с (через Add
) или не уменьшается на достаточно (а Done
вызова не происходит).
Есть ли что-то, что я, очевидно, делаю неправильно? Как бы я проверил, сколько сейчас выполняются подпрограммы в WaitGroup
, поэтому я могу лучше отладить, что происходит?
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"sync"
)
func main() {
links := parseLinks()
var wg sync.WaitGroup
for _, url := range links {
if isExcelDocument(url) {
wg.Add(1)
go downloadFromURL(url, wg)
} else {
fmt.Printf("Skipping: %v \n", url)
}
}
wg.Wait()
}
func downloadFromURL(url string, wg sync.WaitGroup) error {
tokens := strings.Split(url, "/")
fileName := tokens[len(tokens)-1]
fmt.Printf("Downloading %v to %v \n", url, fileName)
content, err := os.Create("temp_docs/" + fileName)
if err != nil {
fmt.Printf("Error while creating %v because of %v", fileName, err)
return err
}
resp, err := http.Get(url)
if err != nil {
fmt.Printf("Could not fetch %v because %v", url, err)
return err
}
defer resp.Body.Close()
_, err = io.Copy(content, resp.Body)
if err != nil {
fmt.Printf("Error while saving %v from %v", fileName, url)
return err
}
fmt.Printf("Download complete for %v \n", fileName)
defer wg.Done()
return nil
}
func isExcelDocument(url string) bool {
return strings.HasSuffix(url, ".xlsx") || strings.HasSuffix(url, ".xls")
}
func parseLinks() []string {
linksData, err := ioutil.ReadFile("links.txt")
if err != nil {
fmt.Printf("Trouble reading file: %v", err)
}
links := strings.Split(string(linksData), ", ")
return links
}
Вы откладываете 'wg.Done()', но у вас все еще есть его в конце функции. Попробуйте переместить его в начало, прежде чем у него появится шанс вернуться от ошибки. –
Передайте указатель на 'wg' функции, а не на структуру. – plusmid