Go如何合并两个切片(在Go中复制文件的三种方法)(1)

本文是 Go 系列的第三篇文章,我将介绍三种最流行的复制文件的方法。

io.Copy

方法一:使用 io.Copy

io.Copycopy
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
  }
os.Stat(src)sourceFileStat.Mode().IsRegular()io.Copy(destination  source)io.Copynil
io.Copy
cp1.go
$ go run cp1.go
Please provide two command line arguments!
$ go run cp1.go fileCP.txt /tmp/fileCPCOPY
Copied 3826 bytes!
$ diff fileCP.txt /tmp/fileCPCOPY

这个方法已经非常简单了,不过它没有为开发者提供灵活性。这并不总是一件坏事,但是,有些时候,开发者可能会需要/想要告诉程序该如何读取文件。

方法二:使用 ioutil.WriteFile 和 ioutil.ReadFile

ioutil.ReadFileioutil.WriteFile

实现代码如下:

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
}
ifioutil.ReadFileioutil.WriteFile
cp2.go
$ go run cp2.go
Please provide two command line arguments!
$ go run cp2.go fileCP.txt /tmp/copyFileCP
$ diff fileCP.txt /tmp/copyFileCP
ioutil.ReadFile

方法三:使用 os.Read 和 os.Write

cp3.go
cp3.goforcopy
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
  }
}
os.Readbufos.Writeio.EOF
cp3.go
$ go run cp3.go
usage: cp3 source destination BUFFERSIZE
$ go run cp3.go fileCP.txt /tmp/buf10 10
Copying fileCP.txt to /tmp/buf10
$ go run cp3.go fileCP.txt /tmp/buf20 20
Copying fileCP.txt to /tmp/buf20
cp3.go

运行基准测试

cp3.gotime(1)
cp1.gocp2.gocp3.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

我们可以看出,这三个程序的性能非常接近,这意味着 Go 标准库函数的实现非常聪明、经过了充分优化。

cp3.gocp3.go
$ ls -l INPUT
-rw-r--r--  1 mtsouk  staff  512000000 Jun  5 09:39 INPUT
$ time go run cp3.go INPUT /tmp/buf10 10
Copying INPUT to /tmp/buf10

real    6m39.721s
user    1m18.457s
sys 5m19.186s
$ time go run cp3.go INPUT /tmp/buf20 20
Copying INPUT to /tmp/buf20

real    3m20.819s
user    0m39.444s
sys 2m40.380s
$ time go run cp3.go INPUT /tmp/buf1000 1000
Copying INPUT to /tmp/buf1000

real    0m4.916s
user    0m1.001s
sys     0m3.986s
cp3.go
cp1.gocp2.gocp3.go

如果你有任何问题或反馈,请在(原文)下方发表评论或在 Twitter上与我(原作者)联系。

via: https://opensource.com/article/18/6/copying-files-go

本文由 LCTT原创编译,Linux中国荣誉推出