并发程序,可以从一个URL列表中同时下载多个文件,并统计总共下载的字节数

63 阅读2分钟

这段代码是一个并发程序,用于从一个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)
}