golang并发下载多个文件的方法
背景说明
假设有一个分布式文件系统,现需要从该系统中并发下载一部分文件到本地机器。
已知该文件系统的部分节点ip,以及需要下载的文件fileID列表,并能通过这些信息来拼接下载地址。
其中节点ip列表保存在xx_node.txt,要下载的fileID保存在xx_fileID.txt中。
代码示例
packagemain
import(
"bufio"
"flag"
"fmt"
"io"
"math/rand"
"net/http"
"os"
"time"
)
var(
clustername=flag.String("clustername","c1","downloadclustername")
)
//逐行读取文件内容
funcReadLines(fpathstring)[]string{
fd,err:=os.Open(fpath)
iferr!=nil{
panic(err)
}
deferfd.Close()
varlines[]string
scanner:=bufio.NewScanner(fd)
forscanner.Scan(){
lines=append(lines,scanner.Text())
}
iferr:=scanner.Err();err!=nil{
fmt.Fprintln(os.Stderr,err)
}
returnlines
}
//实现单个文件的下载
funcDownload(clusternamestring,nodestring,fileIDstring)string{
nt:=time.Now().Format("2006-01-0215:04:05")
fmt.Printf("[%s]Todownload%s\n",nt,fileID)
url:=fmt.Sprintf("http://%s/file/%s",node,fileID)
fpath:=fmt.Sprintf("/yourpath/download/%s_%s",clustername,fileID)
newFile,err:=os.Create(fpath)
iferr!=nil{
fmt.Println(err.Error())
return"processfailedfor"+fileID
}
defernewFile.Close()
client:=http.Client{Timeout:900*time.Second}
resp,err:=client.Get(url)
deferresp.Body.Close()
_,err=io.Copy(newFile,resp.Body)
iferr!=nil{
fmt.Println(err.Error())
}
returnfileID
}
funcmain(){
flag.Parse()
//从文件中读取节点ip列表
nodelist:=ReadLines(fmt.Sprintf("%s_node.txt",*clustername))
iflen(nodelist)==0{
return
}
//从文件中读取待下载的文件ID列表
fileIDlist:=ReadLines(fmt.Sprintf("%s_fileID.txt",*clustername))
iflen(fileIDlist)==0{
return
}
ch:=make(chanstring)
//每个goroutine处理一个文件的下载
r:=rand.New(rand.NewSource(time.Now().UnixNano()))
for_,fileID:=rangefileIDlist{
node:=nodelist[r.Intn(len(nodelist))]
gofunc(node,fileIDstring){
ch<-Download(*clustername,node,fileID)
}(node,fileID)
}
//等待每个文件下载的完成,并检查超时
timeout:=time.After(900*time.Second)
foridx:=0;idx
小结
下载时没有用到默认的httpClient,并指定了超时时间;
下载文件时调用了系统调用,goroutine会被挂起;
下载文件完成后会唤醒被挂起的goroutine,该goroutine执行完后面的代码后便退出;
全局超时控制,超时后主线程退出。
以上这篇golang并发下载多个文件的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。