golang的io.copy使用
程序员文章站
2023-03-26 20:59:49
net/http 下载 在golang中,如果我们要下载一个文件,最简单的就是先用http.get()方法创建一个远程的请求后,后面可使用ioutil.WriteFile()等将请求内容直接写到文件中。 但是你会发现,上面的操作方式会有一个小问题,那就是下载小文件还行,如果是大的文件的话,可能会出现 ......
net/http 下载
在golang中,如果我们要下载一个文件,最简单的就是先用http.get()方法创建一个远程的请求后,后面可使用ioutil.writefile()等将请求内容直接写到文件中。
func downfile() { url :="http://wx.qlogo.cn/vaz7ve1/64" resp ,err := http.get(url) if err != nil { fmt.fprint(os.stderr ,"get url error" , err) } defer resp.body.close() data ,err := ioutil.readall(resp.body) if err != nil { panic(err) } _ =ioutil.writefile("/tmp/icon_wx.png", data, 0755) }
但是你会发现,上面的操作方式会有一个小问题,那就是下载小文件还行,如果是大的文件的话,可能会出现内存不足的问题,因为它是需要先把请求内容全部读取到内存中,然后再写入到文件中的。
那如果要下载大文件或者复制大文件,应该怎么办呢? 其实,golang中就提供了 io.copy
方法,它就是在文件指针之间直接复制的,不用全读入内存,可解决这样的问题。
io.copy
我们先看下原型声明
func copy(dst writer, src reader) (written int64, err error) { return copybuffer(dst, src, nil) } func copybuffer(dst writer, src reader, buf []byte) (written int64, err error) { .... if buf == nil { size := 32 * 1024 if l, ok := src.(*limitedreader); ok && int64(size) > l.n { if l.n < 1 { size = 1 } else { size = int(l.n) } } buf = make([]byte, size) }
它是将源复制到目标,并且是按默认的缓冲区32k循环操作的,不会将内容一次性全写入内存中,这样就能解决大文件的问题。
我们再用 io.copy
来实现一下吧。
func downfile() { url :="http://wx.qlogo.cn/vaz7ve1/64" resp ,err := http.get(url) if err != nil { fmt.fprint(os.stderr ,"get url error" , err) } defer resp.body.close() out, err := os.create("/tmp/icon_wx_2.png") wt :=bufio.newwriter(out) defer out.close() n, err :=io.copy(wt, resp.body) fmt.println("write" , n) if err != nil { panic(err) } wt.flush() }
同理,如果我们要复制大文件也可以用 io.copy
这个,防止产生内存溢出。
上一篇: 从组件文档引发的* ◤1◢
下一篇: JS---案例:开机动画