golang并發(fā)下載多個(gè)文件的方法
背景說明
假設(shè)有一個(gè)分布式文件系統(tǒng),現(xiàn)需要從該系統(tǒng)中并發(fā)下載一部分文件到本地機(jī)器。
已知該文件系統(tǒng)的部分節(jié)點(diǎn)ip, 以及需要下載的文件fileID列表,并能通過這些信息來拼接下載地址。
其中節(jié)點(diǎn)ip列表保存在xx_node.txt, 要下載的fileID保存在xx_fileID.txt中。
代碼示例
package main
import (
"bufio"
"flag"
"fmt"
"io"
"math/rand"
"net/http"
"os"
"time"
)
var (
clustername = flag.String("clustername", "c1", "download clustername")
)
// 逐行讀取文件內(nèi)容
func ReadLines(fpath string) []string {
fd, err := os.Open(fpath)
if err != nil {
panic(err)
}
defer fd.Close()
var lines []string
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, err)
}
return lines
}
// 實(shí)現(xiàn)單個(gè)文件的下載
func Download(clustername string, node string, fileID string) string {
nt := time.Now().Format("2006-01-02 15:04:05")
fmt.Printf("[%s]To download %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)
if err != nil {
fmt.Println(err.Error())
return "process failed for " + fileID
}
defer newFile.Close()
client := http.Client{Timeout: 900 * time.Second}
resp, err := client.Get(url)
defer resp.Body.Close()
_, err = io.Copy(newFile, resp.Body)
if err != nil {
fmt.Println(err.Error())
}
return fileID
}
func main() {
flag.Parse()
// 從文件中讀取節(jié)點(diǎn)ip列表
nodelist := ReadLines(fmt.Sprintf("%s_node.txt", *clustername))
if len(nodelist) == 0 {
return
}
// 從文件中讀取待下載的文件ID列表
fileIDlist := ReadLines(fmt.Sprintf("%s_fileID.txt", *clustername))
if len(fileIDlist) == 0 {
return
}
ch := make(chan string)
// 每個(gè)goroutine處理一個(gè)文件的下載
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for _, fileID := range fileIDlist {
node := nodelist[r.Intn(len(nodelist))]
go func(node, fileID string) {
ch <- Download(*clustername, node, fileID)
}(node, fileID)
}
// 等待每個(gè)文件下載的完成,并檢查超時(shí)
timeout := time.After(900 * time.Second)
for idx := 0; idx < len(fileIDlist); idx++ {
select {
case res := <-ch:
nt := time.Now().Format("2006-01-02 15:04:05")
fmt.Printf("[%s]Finish download %s\n", nt, res)
case <-timeout:
fmt.Println("Timeout...")
break
}
}
}
小結(jié)
下載時(shí)沒有用到默認(rèn)的http Client, 并指定了超時(shí)時(shí)間;
下載文件時(shí)調(diào)用了系統(tǒng)調(diào)用, goroutine會(huì)被掛起;
下載文件完成后會(huì)喚醒被掛起的goroutine, 該goroutine執(zhí)行完后面的代碼后便退出;
全局超時(shí)控制,超時(shí)后主線程退出。
以上這篇golang并發(fā)下載多個(gè)文件的方法就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 使用google-perftools優(yōu)化nginx在高并發(fā)時(shí)的性能的教程(完整版)
- Golang極簡入門教程(三):并發(fā)支持
- Go語言并發(fā)技術(shù)詳解
- Go語言并發(fā)模型的2種編程方案
- GO語言并發(fā)編程之互斥鎖、讀寫鎖詳解
- Go語言如何并發(fā)超時(shí)處理詳解
- 如何利用Golang寫出高并發(fā)代碼詳解
- golang實(shí)現(xiàn)并發(fā)數(shù)控制的方法
- 詳解Golang 中的并發(fā)限制與超時(shí)控制
- golang中sync.Map并發(fā)創(chuàng)建、讀取問題實(shí)戰(zhàn)記錄
- Go 并發(fā)實(shí)現(xiàn)協(xié)程同步的多種解決方法
- 在Go中構(gòu)建并發(fā)TCP服務(wù)器
- Go 并發(fā)控制context實(shí)現(xiàn)原理剖析(小結(jié))
- Go并發(fā)調(diào)用的超時(shí)處理的方法
- golang 并發(fā)安全Map以及分段鎖的實(shí)現(xiàn)方法
- Golang 實(shí)現(xiàn)分片讀取http超大文件流和并發(fā)控制
- golang gin 框架 異步同步 goroutine 并發(fā)操作
- Go并發(fā)4種方法簡明講解
相關(guān)文章
go項(xiàng)目實(shí)現(xiàn)mysql接入及web?api的操作方法
這篇文章主要介紹了go項(xiàng)目實(shí)現(xiàn)mysql接入以及web api,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08
Go通過goroutine實(shí)現(xiàn)多協(xié)程文件上傳的基本流程
多協(xié)程文件上傳是指利用多線程或多協(xié)程技術(shù),同時(shí)上傳一個(gè)或多個(gè)文件,以提高上傳效率和速度,本文給大家介紹了Go通過goroutine實(shí)現(xiàn)多協(xié)程文件上傳的基本流程,需要的朋友可以參考下2024-05-05
Go?基本數(shù)據(jù)類型與字符串相互轉(zhuǎn)換方法小結(jié)
這篇文章主要介紹了Go基本數(shù)據(jù)類型與字符串相互轉(zhuǎn)換,將string類型轉(zhuǎn)換成基本類型時(shí),必須確保string類型是有效的,文中補(bǔ)充介紹了Go基本數(shù)據(jù)類型和其字符串表示之間轉(zhuǎn)換,結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2024-01-01
Go語言LeetCode題解961在長度2N的數(shù)組中找出重復(fù)N次元素
這篇文章主要為大家介紹了Go語言LeetCode題解961在長度2N的數(shù)組中找出重復(fù)N次元素示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
golang快速實(shí)現(xiàn)網(wǎng)頁截圖的方法
這篇文章主要介紹了golang快速實(shí)現(xiàn)網(wǎng)頁截圖的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
深入string理解Golang是怎樣實(shí)現(xiàn)的
這篇文章主要為大家介紹了深入string理解Golang是怎樣實(shí)現(xiàn)的原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04

