文件格式为
http://www.host.com/AAA001.dat
http://www.host.com/AAA002.dat
...
http://www.host.com/BBB001.dat
http://www.host.com/BBB002.dat
文件为AAA、BBB、CCC开头,后面为递增数字,数量未知。
希望能3线程下载,不清楚如何实现,是否要每个下载都启动一个新的goroutine来处理?
按照你的需求,其实是构造一个闭环系统。
因此重要的就是考虑什么时候结束这个闭环。
```
package main
import (
"fmt"
"sync"
)
// URLInfo 保留构造下载链接的信息
type URLInfo struct {
url string
page int
}
func download(info URLInfo) bool {
if info.page < 10 {
fmt.Printf("%s%03d.dat downloaded \n", info.url, info.page)
} else {
fmt.Printf("%s%03d.dat download fail \n", info.url, info.page)
}
return info.page < 10
}
func main() {
in := make(chan URLInfo, 1)
out := make(chan URLInfo, 1)
var wg sync.WaitGroup
// 分配3个goroutines来下载文件
for i := 0; i < 3; i++ {
go func() {
for url := range in {
if download(url) {
// 下载后续三个文件
wg.Add(3)
go func(url URLInfo) {
for id := 1; id <= 3; id++ {
out <- URLInfo{
url: url.url,
page: url.page + id,
}
}
}(url)
}
wg.Done()
}
}()
}
// 初始化下载.
wg.Add(1)
go func() {
for _, uri := range []URLInfo{{"AAA", 1}, {"BBB", 1}, {"CCC", 1}} {
wg.Add(1)
out <- uri
}
wg.Done()
}()
// 分发下载任务,过滤重复的文件
go func() {
urls := make(map[URLInfo]struct{})
for uri := range out {
if _, ok := urls[uri]; ok {
wg.Done()
} else {
urls[uri] = struct{}{}
in <- uri
}
}
}()
wg.Wait()
// 这里所有文件都已经下载完成。
}
```
#11
更多评论
用channel配合生产者/消费者模式,就可以控制下载的gorountine数目。
大致流程如下:
```
const (
ThreadCount = 3
)
func main() {
ch := make(chan string, ThreadCount)
var wg sync.WaitGroup
for i := 0; i < ThreadCount; i++ {
wg.Add(1)
go func() {
for url := range ch {
download(url)
}
wg.Done()
}()
}
urls := []string{
"http://www.host.com/AAA001.dat",
"http://www.host.com/AAA002.dat",
//...
}
// 分派下载任务
for _, url := range urls {
ch <- url
}
close(ch)
wg.Wait()
}
```
#1
多谢解答。但是下载数量未知如何解决呢?比如AAA是到了AAA247.dat,但是预先不知道数量,只有尝试AAA247.dat下载失败才知道需要结束,其它BBB、CCC也是如此。
#2