• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    golang并发下载多个文件的方法

    背景说明

    假设有一个分布式文件系统,现需要从该系统中并发下载一部分文件到本地机器。

    已知该文件系统的部分节点ip, 以及需要下载的文件fileID列表,并能通过这些信息来拼接下载地址。

    其中节点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")
    )
    
    // 逐行读取文件内容
    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
    }
    
    // 实现单个文件的下载
    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()
    
      // 从文件中读取节点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)
    
      // 每个goroutine处理一个文件的下载
      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)
      }
    
      // 等待每个文件下载的完成,并检查超时
      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
        }
      }
    }

    小结

    下载时没有用到默认的http Client, 并指定了超时时间;

    下载文件时调用了系统调用, goroutine会被挂起;

    下载文件完成后会唤醒被挂起的goroutine, 该goroutine执行完后面的代码后便退出;

    全局超时控制,超时后主线程退出。

    以上这篇golang并发下载多个文件的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

    您可能感兴趣的文章:
    • golang语言实现的文件上传与文件下载功能示例
    • Golang实现异步上传文件支持进度条查询的方法
    • Golang+Android基于HttpURLConnection实现的文件上传功能示例
    • golang简单获取上传文件大小的实现代码
    • 如何使用大学教育邮箱下载golang等软件(推荐)
    • 解决 Golang VS Code 插件下载安装失败的问题
    • golang实现http server提供文件下载功能
    • Golang 使用http Client下载文件的实现方法
    • 下载golang.org/x包的操作方法
    • golang实现的文件上传下载小工具
    上一篇:golang socket断点续传大文件的实现方法
    下一篇:golang并发ping主机的方法
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    golang并发下载多个文件的方法 golang,并发,下载,多个,文件,