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并发下载多个文件的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。