我有以下代码来获取URL的列表,然后有条件地下载文件并将其保存到文件系统.同时获取文件,主goroutine等待获取所有文件.但是,在完成所有请求后,程序永远不会退出(并且没有错误).
我认为正在发生的事情是,以某种方式,其中的例程量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
}
Run Code Online (Sandbox Code Playgroud)
Bar*_*osz 29
这段代码有两个问题.首先,您必须将指向WaitGroup的指针传递给downloadFromURL()
,否则该对象将被复制并且Done()
不会在其中可见main()
.
看到:
func main() {
...
go downloadFromURL(url, &wg)
...
}
Run Code Online (Sandbox Code Playgroud)
第二,defer wg.Done()
应该是第一个语句之一downloadFromURL()
,否则如果你从该语句之前的函数返回,它将不会被"注册"而不会被调用.
func downloadFromURL(url string, wg *sync.WaitGroup) error {
defer wg.Done()
...
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5460 次 |
最近记录: |