Golang使用goroutines并行下载多个文件 [英] Golang download multiple files in parallel using goroutines

查看:164
本文介绍了Golang使用goroutines并行下载多个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以使用goroutines并行下载和保存文件?



下面是我的代码,从我的dropbox下载文件:

  package main 

import(
encoding / json
fmt
io
io / ioutil
net / http
net / url
os
path / filepath
) b
$ b const app_key string =< app_key>
const app_secret string =< app_secret>

var code string

type TokenResponse struct {
AccessToken string`json:access_token`
}

文件struct {
路径字符串
}

类型FileListResponse struct {
FileList []文件`json:contents`
}

func download_file(file file,token TokenResponse){

download_file:= fmt.Sprintf(https://api-content.dropbox.com/1/files/dropbox/%s ?access_token =%s,file.Path,token.AccessToken)

resp,_:= http.Get(download_file)
defer respBody.Close()

filename:= filepath.Base(file.Path)
out,err:= os.Create(filename)
if err!= nil {
panic $ b}
defer out.Close()

io.Copy(out,respBody)
}

func main b
$ b authorize_url:= fmt.Sprintf(https://www.dropbox.com/1/oauth2/authorize?response_type=code&client_id=%s,app_key)

//获取代码
fmt.Printf(1。转到:%s\\\
,authorize_url)
fmt.Println(2.单击允许(您可能必须先登录))
fmt.Println授权码)
fmt.Printf(在此输入授权码)
fmt.Scanf(%s,& code)
//结束获取代码

//获取访问令牌
data:= url.Values {}
data.Add(code,code)
data.Add(grant_type authorization_code)
data.Add(client_id,app_key)
data.Add(client_secret,app_secret)

resp,_:= http.PostForm https://api.dropbox.com/1/oauth2/token,data)
defer respBody.Close()

contents,_:= ioutil.ReadAll身体)

var tr TokenResponse

json.Unmarshal(contents,& tr)
//结束获取访问令牌

/ /获取文件列表
file_list_url:= fmt.Sprintf(https://api.dropbox.com/1/metadata/dropbox/Camera Uploads?access_token =%s,tr.AccessToken)

resp2,_:= http.Get(file_list_url)
defer resp2.Body.Close()

contents2,_:= ioutil.ReadAll(resp2.Body)

var flr FileListResponse
json.Unmarshal(contents2,& flr)
//结束获取文件列表

for i,file:= range flr.FileList {

download_file(file,tr)

if i> = 2 {
break
}
}
}



当我在download_file函数前面加上 go 命令。

  go download_file(file,tr)


解决方案

这是因为你的主goroutine正在退出。您需要添加一个WaitGroup等待,直到所有的goroutines退出。例如,

  var wg sync.WaitGroup 
for i,file:= range flr.FileList {
wg.Add(1)

go download_file(file,tr,wg)

如果i> = 2 {
break
} b $ b}
wg.Wait()

...
func download_file(file file,token TokenResponse,wg sync.WaitGroup){
...
wg.Done()
}


Is it possible to download and save files in parallel using goroutines?

Below is my code which downloads files from my dropbox:

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "io/ioutil"
    "net/http"
    "net/url"
    "os"
    "path/filepath"
)

const app_key string = "<app_key>"
const app_secret string = "<app_secret>"

var code string

type TokenResponse struct {
    AccessToken string `json:"access_token"`
}

type File struct {
    Path string
}

type FileListResponse struct {
    FileList []File `json:"contents"`
}

func download_file(file File, token TokenResponse) {

    download_file := fmt.Sprintf("https://api-content.dropbox.com/1/files/dropbox/%s?access_token=%s", file.Path, token.AccessToken)

    resp, _ := http.Get(download_file)
    defer resp.Body.Close()

    filename := filepath.Base(file.Path)
    out, err := os.Create(filename)
    if err != nil {
        panic(err)
    }
    defer out.Close()

    io.Copy(out, resp.Body)
}

func main() {

    authorize_url := fmt.Sprintf("https://www.dropbox.com/1/oauth2/authorize?response_type=code&client_id=%s", app_key)

    // Get code
    fmt.Printf("1. Go to: %s\n", authorize_url)
    fmt.Println("2. Click 'Allow' (you might have to log in first)")
    fmt.Println("3. Copy the authorization code.")
    fmt.Printf("Enter the authorization code here: ")
    fmt.Scanf("%s", &code)
    // End get code

    // Get access token
    data := url.Values{}
    data.Add("code", code)
    data.Add("grant_type", "authorization_code")
    data.Add("client_id", app_key)
    data.Add("client_secret", app_secret)

    resp, _ := http.PostForm("https://api.dropbox.com/1/oauth2/token", data)
    defer resp.Body.Close()

    contents, _ := ioutil.ReadAll(resp.Body)

    var tr TokenResponse

    json.Unmarshal(contents, &tr)
    // End get access token

    // Get file list
    file_list_url := fmt.Sprintf("https://api.dropbox.com/1/metadata/dropbox/Camera Uploads?access_token=%s", tr.AccessToken)

    resp2, _ := http.Get(file_list_url)
    defer resp2.Body.Close()

    contents2, _ := ioutil.ReadAll(resp2.Body)

    var flr FileListResponse
    json.Unmarshal(contents2, &flr)
    // End get file list

    for i, file := range flr.FileList {

        download_file(file, tr)

        if i >= 2 {
            break
        }
    }
}

It doesn't work when I prefix the download_file function with the go command.

go download_file(file, tr)

解决方案

That's because your main goroutine is exiting. You need to add a WaitGroup to wait until all the goroutines exit. For example,

var wg sync.WaitGroup
for i, file := range flr.FileList {
    wg.Add(1)

    go download_file(file, tr, wg)

    if i >= 2 {
        break
    }
}
wg.Wait()

...
func download_file(file File, token TokenResponse, wg sync.WaitGroup) {
    ...
    wg.Done()
}

这篇关于Golang使用goroutines并行下载多个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆