Go语言中拷贝文件的几种常用的方式

简介
本篇文章将介绍Go语言中,最最最常用的3种拷贝文件的方法,这三种方法各有利弊,我们只需要在应用中选择最合适的即可,不必盲目追求性能。
方法1
第一个方法将使用标准Go库的io.Copy()函数。以下是使用io.Copy()实现的拷贝文件代码片段:
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(),但由于使用一次性读取文件,再一次性写入文件的方式,所以该方法不适用于大文件,容易内存溢出。
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
}
}性能
这三种方式都能很方便的实现拷贝文件功能,那他们的性能如何呢,下面我们来尝试对比一下。三种方式都来拷贝同一个500M的文件,
以下是拷贝文件的时间明细(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 1000000Copying INPUT to /tmp/cp3 real 0m1.025s user 0m0.195s sys 0m0.486s
从以上数据来看3种方式的性能非常接近,但依然可以看出Go的io标准包的性能更优。
作者:freelang
链接:https://www.jianshu.com/p/6cc1938260ba
随时随地看视频