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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM