文件格式为
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来处理?
我仿照书上的写个一个,有个问题,程序结束后会报fatal error: all goroutines are asleep - deadlock!
`
package main
import (
"fmt"
"time"
)
// URLInfo 保留构造下载链接的信息
type URLInfo struct {
urltype string
page int
}
func download1(info URLInfo) bool {
time.Sleep(time.Second)
if info.page < 10 {
fmt.Printf("%s%03d.dat downloaded \n", info.urltype, info.page)
} else {
fmt.Printf("%s%03d.dat download fail \n", info.urltype, info.page)
}
return (info.page < 10)
}
func main() {
urllist := make(chan []URLInfo) // 预测可能的文件列表,允许重复
undownLinks := make(chan URLInfo) // 待下载文件URLs,不重复
// 初始化下载.
go func() { urllist <- []URLInfo{{"AAA", 1}, {"BBB", 1}, {"CCC", 1}} }()
// 分配3个goroutines来下载文件
for i := 0; i < 3; i++ {
go func() {
for ui := range undownLinks {
if download1(ui) {
urls := []URLInfo{{ui.urltype, ui.page + 1}, {ui.urltype, ui.page + 2}, {ui.urltype, ui.page + 3}}
go func() { urllist <- urls }()
}
}
}()
}
// 通过主goroutine来过滤重复的文件列表,将未下载的文件发送至undownLinks
downedLinks := make(map[URLInfo]bool)
for list := range urllist {
for _, link := range list {
if !downedLinks[link] {
downedLinks[link] = true
undownLinks <- link
}
}
}
close(urllist)
close(undownLinks)
}
`
#5
更多评论
用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