这段代码是一个并发程序,用于从一个URL列表中同时下载多个文件,并统计总共下载的字节数。
首先,我们定义了一个 download 函数,它接收一个URL字符串、一个 sync.WaitGroup 对象和一个 chan int 通道作为参数。该函数的作用是下载指定URL的文件,并将下载的字节数发送到通道中。
在 download 函数中,我们使用 http.Get 方法来发送GET请求获取URL对应的响应。然后,我们使用 ioutil.ReadAll 方法读取响应的全部内容,并将读取的字节数发送到通道中。最后,我们打印下载完成的消息。
在 main 函数中,我们定义了一个URL列表 urls,其中包含了要下载的文件的URL。然后,我们创建了一个 sync.WaitGroup 对象 wg 和一个 chan int 通道 ch。
接下来,我们使用 for range 循环遍历URL列表,对于每个URL,我们调用 wg.Add(1) 来增加 WaitGroup 的计数器,并使用 go 关键字启动一个新的goroutine来并发下载文件。我们将 &wg 和 ch 作为参数传递给 download 函数。
在 main 函数中,我们还启动了一个匿名的goroutine,使用 wg.Wait() 来等待所有下载任务完成,并在完成后关闭通道。
最后,我们使用 for range 循环遍历通道 ch,并将每次接收到的字节数累加到 totalBytes 变量中。最后,我们打印出总共下载的字节数。
总体来说,这段代码展示了如何使用goroutine和通道实现并发下载,并使用 sync.WaitGroup 来等待所有下载任务完成。通过使用并发,可以同时下载多个文件,提高下载效率。
package main
import (
"fmt"
"io/ioutil"
"net/http"
"sync"
)
// 并发程序,可以从一个URL列表中同时下载多个文件,并统计总共下载的字节数
func download(url string, wg *sync.WaitGroup, ch chan int) {
defer wg.Done()
resp, err := http.Get(url)
if err != nil {
fmt.Printf("Error downloading %s: %v\n", url, err)
return
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Error reading response body for %s: %v\n", url, err)
return
}
ch <- len(data)
fmt.Printf("%s downloaded (%d bytes)\n", url, len(data))
}
func main() {
urls := []string{
"https://www.example.com/",
"https://golang.org/",
"https://www.google.com/",
}
var wg sync.WaitGroup
ch := make(chan int)
for _, url := range urls {
wg.Add(1)
go download(url, &wg, ch)
}
go func() {
wg.Wait()
close(ch)
}()
totalBytes := 0
for bytes := range ch {
totalBytes += bytes
}
fmt.Printf("Total bytes downloaded: %d\n", totalBytes)
}