如何在Go中将HTTP响应传递给文件?

eka*_*nna 34 go

如何将以下代码转换为使用流/管道,以便我不需要将完整内容读入内存?就像是: http.Get("http://example.com/").Pipe("./data.txt")

package main
import ("net/http";"io/ioutil")

func main() {
        resp, err := http.Get("http://example.com/")
        check(err)
        defer resp.Body.Close()
        body, err := ioutil.ReadAll(resp.Body)
        check(err)
        err = ioutil.WriteFile("./data.txt", body, 0666)
        check(err)
}
func check(e error) {
        if e != nil {
                panic(e)
        }
}
Run Code Online (Sandbox Code Playgroud)

bur*_*rfl 52

怎么样io.Copy()?其文档可在以下网址找到:http://golang.org/pkg/io/#Copy

不过,这很简单.给它一个io.Reader和一个io.Writer并且它将数据一次复制一个小块(例如,不是一次全部存储在内存中).

所以你可能会尝试写下这样的东西:

func main() {
  resp, err := http.Get("...")
  check(err)
  defer resp.Body.Close()
  out, err := os.Create("filename.ext")
  if err != nil {
    // panic?
  }
  defer out.Close()
  io.Copy(out, resp.Body)
}
Run Code Online (Sandbox Code Playgroud)

我没有测试过上面的内容; 我刚从上面的例子中快速地将它一起攻击,但如果不是钱,它应该很接近.

  • 您可以使用它,所以你可以`推迟checkClose(IO,与ERR)` - 那么这将改变返回函数的返回代码,以指示关闭发生错误,[给人一种延迟的便利,但正确返回错误](HTTPS ://github.com/ncw/swift/blob/master/swift.go#L345). (8认同)
  • 我很高兴有很多关于不检查`Close()`的错误的评论(好主意!)但是没有人提到(可以说)更重要的失败来检查`io.Copy的错误返回. (8认同)
  • 这是[checkClose](https://github.com/ncw/swift/blob/master/swift.go#L114),它显示了如何检查延迟关闭时的错误.如果您重视数据完整性,请不要忽略关闭时的错误!如果close返回错误,则需要将其报告给用户.从Linux手册页:不检查close()的返回值是一个常见但严重的编程错误.很可能在最后的close()上首先报告先前write()操作的错误.关闭文件时不检查返回值可能会导致数据无声丢失. (7认同)
  • @Nick这是非常常见的(甚至是惯用的),但是,推迟关闭并忽略错误.除了操作系统中的尖叫声之外,通常没有太多关于紧密错误的事情. (4认同)
  • 请注意,此代码不检查任何一个`Close()`语句的错误返回. (3认同)
  • 从 Go 1.16 开始,本答案中对 io.Copy 的调用在幕后使用了 [File.ReadFrom](https://golang.org/pkg/os#File.ReadFrom)。使用 io.Copy 的一个很好的功能是 io.Copy 使用最佳的可用复制机制。最好使用 io.Copy 而不是自己选择较低级别的复制函数。 (2认同)

小智 8

另一个选项是File.ReadFrom

package main

import (
   "net/http"
   "os"
)

func main() {
   r, e := http.Get("http://speedtest.lax.hivelocity.net")
   if e != nil {
      panic(e)
   }
   defer r.Body.Close()
   f, e := os.Create("index.html")
   if e != nil {
      panic(e)
   }
   defer f.Close()
   f.ReadFrom(r.Body)
}
Run Code Online (Sandbox Code Playgroud)