golang的io.copy使用

net/http 下載

在golang中,若是咱們要下載一個文件,最簡單的就是先用http.get()方法建立一個遠程的請求後,後面可以使用ioutil.WriteFile()等將請求內容直接寫到文件中。golang

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)
}

可是你會發現,上面的操做方式會有一個小問題,那就是下載小文件還行,若是是大的文件的話,可能會出現內存不足的問題,由於它是須要先把請求內容所有讀取到內存中,而後再寫入到文件中的。url

那若是要下載大文件或者複製大文件,應該怎麼辦呢? 其實,Golang中就提供了 io.copy方法,它就是在文件指針之間直接複製的,不用全讀入內存,可解決這樣的問題。指針

io.copy

咱們先看下原型聲明code

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 來實現一下吧。get

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 這個,防止產生內存溢出。原型

相關文章
相關標籤/搜索