3 回答
TA贡献1802条经验 获得超5个赞
这段代码有两个问题。首先,您必须将指向 WaitGroup 的指针传递给downloadFromURL(),否则对象将被复制并且Done()在 中不可见main()。
看:
func main() {
...
go downloadFromURL(url, &wg)
...
}
其次,defer wg.Done()应该是 中的第一个语句之一downloadFromURL(),否则如果您从该语句之前的函数返回,它将不会被“注册”并且不会被调用。
func downloadFromURL(url string, wg *sync.WaitGroup) error {
defer wg.Done()
...
}
TA贡献1784条经验 获得超8个赞
Go 中的参数总是按值传递。当参数可能被修改时使用指针。另外,请确保您始终执行wg.Done()。例如,
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"sync"
)
func main() {
links := parseLinks()
wg := new(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 {
defer wg.Done()
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)
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
}
- 3 回答
- 0 关注
- 230 浏览
添加回答
举报