我正在尝试编写一个可下载一系列图像的应用程序。
go go go1.9.2 darwin / amd64
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
"sync"
)
func main() {
var urls []string
// var smallImage = "https://s3.amazonaws.com/golangplayground/116kb.jpeg" //116kb
var largeImage = "https://s3.amazonaws.com/golangplayground/SampleJPGImage_500kbmb.jpg" //500kb
for i := 0; i < 130; i++ {
urls = append(urls, largeImage)
}
var wg sync.WaitGroup
wg.Add(len(urls))
var inc = 0
for _, val := range urls {
inc += 1
go saveResourceFromURLToDisk(val, "./foo", &wg, inc)
}
wg.Wait()
fmt.Println("done.")
}
func saveResourceFromURLToDisk(url string, writeTo string, wg *sync.WaitGroup, inc int) error {
defer wg.Done()
response, err := http.Get(url)
if err != nil {
log.Fatal(err)
return err
}
defer response.Body.Close()
localPath := fmt.Sprintf("%s/%d", writeTo, inc)
file, err := os.Create(localPath)
if err != nil {
log.Fatal(err)
return err
}
defer file.Close()
_, err = io.Copy(file, response.Body)
if err != nil {
log.Fatal(err)
return err
}
fmt.Println(localPath)
return nil
}
答案 0 :(得分:1)
这可能是一个网络问题。 Web浏览器对打开同一服务器的会话数量有限制的原因。
如果同时打开一堆TCP会话,几乎所有TCP会话都会丢失数据包。然后他们都会尝试在大约相同的时间重试,丢失更多的数据包。这只是一大堆失败。
在打开每个GET请求之间放置一个小延迟,或限制自己同时从同一服务器下载4-8个。
答案 1 :(得分:0)
我在Zan的帮助下找到了答案,通过在每个5个请求中分解我的例程......这样我就可以利用一些并行性来限制我正在创建的开放连接的数量。
它有点幼稚,我想知道是否有人有更优雅的解决方案。
package main
import (
"fmt"
"io"
"log"
"net/http"
"os"
"sync"
)
func main() {
var urls []string
// var smallImage = "https://s3.amazonaws.com/golangplayground/116kb.jpeg" //116kb
var largeImage = "https://s3.amazonaws.com/golangplayground/SampleJPGImage_500kbmb.jpg" //500kb
for i := 0; i < 150; i++ {
urls = append(urls, largeImage)
}
var inc = 0;
for x:=0; x < len(urls)/5; x++ {
var wg sync.WaitGroup
for y:=0; y<5; y++ {
wg.Add(1)
go saveResourceFromURLToDisk(urls[x*y], "./foo", &wg, inc)
inc += 1
}
wg.Wait()
}
fmt.Println("done.")
}
func saveResourceFromURLToDisk(url string, writeTo string, wg *sync.WaitGroup, inc int) error {
defer wg.Done()
response, err := http.Get(url)
if err != nil {
log.Fatal(err)
return err
}
defer response.Body.Close()
localPath := fmt.Sprintf("%s/%d", writeTo, inc)
file, err := os.Create(localPath)
if err != nil {
log.Fatal(err)
return err
}
defer file.Close()
_, err = io.Copy(file, response.Body)
if err != nil {
log.Fatal(err)
return err
}
fmt.Println(localPath)
return nil
}