Go語言中拷貝文件的幾種常用的方式
回復(fù)“Go語言”即可獲贈Python從入門到進階共10本電子書
Go語言中拷貝文件的幾種常用的方式

“ 閱讀本文大概需要4.2分鐘 ”
簡介
本篇文章將介紹Go語言中,最最最常用的3種拷貝文件的方法,這三種方法各有利弊,我們只需要在應(yīng)用中選擇最合適的即可,不必盲目追求性能。
方法1
第一個方法將使用標(biāo)準(zhǔn)Go庫的 io.Copy()函數(shù)。以下是使用io.Copy()實現(xiàn)的拷貝文件代碼片段:
func copy(src, dst string) (int64, error) {
? ? ? ?sourceFileStat, err := os.Stat(src)
? ? ? ?if err != nil {
? ? ? ? ? ? ? ?return 0, err
? ? ? ?}
? ? ? ?if !sourceFileStat.Mode().IsRegular() {
? ? ? ? ? ? ? ?return 0, fmt.Errorf("%s is not a regular file", src)
? ? ? ?}
? ? ? ?source, err := os.Open(src)
? ? ? ?if err != nil {
? ? ? ? ? ? ? ?return 0, err
? ? ? ?}
? ? ? ?defer source.Close()
? ? ? ?destination, err := os.Create(dst)
? ? ? ?if err != nil {
? ? ? ? ? ? ? ?return 0, err
? ? ? ?}
? ? ? ?defer destination.Close()
? ? ? ?nBytes, err := io.Copy(destination, source)
? ? ? ?return nBytes, err
}
方法二
第二中方法是使用ioutil包中的 ioutil.WriteFile()和 ioutil.ReadFile(),但由于使用一次性讀取文件,再一次性寫入文件的方式,所以該方法不適用于大文件,容易內(nèi)存溢出。
input, err := ioutil.ReadFile(sourceFile)
? ? ? ?if err != nil {
? ? ? ? ? ? ? ?fmt.Println(err)
? ? ? ? ? ? ? ?return
? ? ? ?}
? ? ? ?err = ioutil.WriteFile(destinationFile, input, 0644)
? ? ? ?if err != nil {
? ? ? ? ? ? ? ?fmt.Println("Error creating", destinationFile)
? ? ? ? ? ? ? ?fmt.Println(err)
? ? ? ? ? ? ? ?return
? ? ? ?}
方法三
最后是使用os包中的 os.Read() 和 os.Write(),此方法是按塊讀取文件,塊的大小也會影響到程序的性能。
?buf := make([]byte, BUFFERSIZE)
? ? ? ?for {
? ? ? ? ? ? ? ?n, err := source.Read(buf)
? ? ? ? ? ? ? ?if err != nil && err != io.EOF {
? ? ? ? ? ? ? ? ? ? ? ?return err
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?if n == 0 {
? ? ? ? ? ? ? ? ? ? ? ?break
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?if _, err := destination.Write(buf[:n]); err != nil {
? ? ? ? ? ? ? ? ? ? ? ?return err
? ? ? ? ? ? ? ?}
? ? ? ?}
性能
這三種方式都能很方便的實現(xiàn)拷貝文件功能,那他們的性能如何呢,下面我們來嘗試對比一下。三種方式都來拷貝同一個500M的文件,
以下是拷貝文件的時間明細(xì)( cp1.go是第一種方式, cp2.go是第二種方式, cp3.go是第三種方式)
$ ls -l INPUT
-rw-r--r-- ?1 mtsouk ?staff ?512000000 Jun ?5 09:39 INPUT
$ time go run cp1.go INPUT /tmp/cp1
Copied 512000000 bytes!
real ? ?0m0.980s
user ? ?0m0.219s
sys ? ? 0m0.719s
$ time go run cp2.go INPUT /tmp/cp2
real ? ?0m1.139s
user ? ?0m0.196s
sys ? ? 0m0.654s
$ time go run cp3.go INPUT /tmp/cp3 1000000
Copying INPUT to /tmp/cp3
real ? ?0m1.025s
user ? ?0m0.195s
sys ? ? 0m0.486s
從以上數(shù)據(jù)來看3種方式的性能非常接近,但依然可以看出Go的io標(biāo)準(zhǔn)包的性能更優(yōu)。
推薦閱讀:
Go的并發(fā)沒有它,就像iphone沒有網(wǎng)絡(luò)一樣
-------------------?End?-------------------

歡迎大家點贊,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持
想加入學(xué)習(xí)群請在后臺回復(fù)【入群】
萬水千山總是情,點個【在看】行不行
