golang的io.copy使用

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 这个,防止产生内存溢出。

原文地址:https://www.cnblogs.com/smartrui/p/12110576.html

时间: 2024-10-19 19:33:26

golang的io.copy使用的相关文章

golang的io包

package io import "io" io包提供了对I/O原语的基本接口.本包的基本任务是包装这些原语已有的实现(如os包里的原语),使之成为共享的公共接口,这些公共接口抽象出了泛用的函数并附加了一些相关的原语的操作. 因为这些接口和原语是对底层实现完全不同的低水平操作的包装,除非得到其它方面的通知,客户端不应假设它们是并发执行安全的. Index Variables type Reader type Writer type Closer type Seeker type Re

golang 中io包用法(一)

本文转自Golove博客:http://www.cnblogs.com/golove/p/3276678.html io 包为I/O原语提供了基础的接口.它主要包装了这些原语的已有实现,如 os 包中的那些,抽象成函数性的共享公共接口,加上一些其它相关的原语. 由于这些接口和原语以不同的实现包装了低级操作,因此除非另行通知,否则客户不应假定它们对于并行执行是安全的. 在io包中最重要的是两个接口:Reader和Writer接口,首先来介绍这两个接口. type Reader interface

golang把io.ReadCloser类型转化为[]byte

//比如要解析resp.Body(io.ReadCloser),我们可以这样处理 body, err := ioutil.ReadAll(resp.Body) 接着,我们继续分析分析函数 func ReadAll(r io.Reader) ([]byte, error) { return readAll(r, bytes.MinRead) //const MinRead = 512 } // func readAll(r io.Reader, capacity int64) (b []byte,

关于golang中IO相关的Buffer类浅析

io重要的接口 在介绍buffer之前,先来认识两个重要的接口,如下边所示: type Reader interface { Read(p []byte) (n int, err error) } type Writer interface { Write(p []byte) (n int, err error) } 上边两个接口在golang sdk安装目录src/io/io.go中定义.后边凡是涉及到io相关操作的,基本上都实现了这两个接口,如: 1. package bufio 中的Rea

golang:IO File 操作

1,创建文件 /*createFile 创建文件 | 参数说明:dir 路径,fileName 文件名 */ func createFile(dir, fileName string) (*os.File, error) { var err error //目录不存在则创建 if _, err = os.Stat(dir); err != nil { if err = os.MkdirAll(dir, 0777); err != nil { //这里如果是0711权限 可能会导致其它线程,读取文

Golang进阶实战之IO操作

文件读写 12345678910111213141516171819202122232425262728293031323334 func () { fileInfo, err := os.Stat("aaa.txt") if err != nil { fmt.Println("error") return } fmt.Println(fileInfo) fmt.Println(fileInfo.Name()) fmt.Println(fileInfo.Size()

Golang基础学习总结

1.不支持继承 重载 ,比如C++Java的接口,接口的修改会影响整个实现改接口的类行为的修改,Go 设计者认为这一特点或许根本没用. 2.必任何函数定义必须花括号跟在函数声明后面而不能换行 如 func  funca(a int){},在Go语言中 函数也是一种类型 可以被推导  使用支持匿名函数 和闭包. 函数的返回值支持多重返回类似Python , 如果不赋值  整数类型默认 0     浮点数类型默认0.0   error类型 默认是nil 3.不用的包一定不要引入,这是Go的原则,就如

golang中defer的使用规则

在golang当中,defer代码块会在函数调用链表中增加一个函数调用.这个函数调用不是普通的函数调用,而是会在函数正常返回,也就是return之后添加一个函数调用.因此,defer通常用来释放函数内部变量. 为了更好的学习defer的行为,我们首先来看下面一段代码: func CopyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName)if err != nil {retu

[转]50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs

http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/ 50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs Go is a simple and fun language, but, like any other language, it has a few gotchas... Many of those gotc