Go copy file
last modified April 29, 2025
This tutorial demonstrates how to copy files in Golang using various methods. We explore five distinct approaches to copying a file, showcasing different Go packages and functions. Each method offers unique advantages depending on the use case, such as simplicity, performance, or fine-grained control.
We utilize functions like ioutil.ReadFile
, ioutil.WriteFile
,
io.Copy
, File.Read
, File.Write
, and
others from Go's standard library to perform file copying operations
efficiently.
$ go version go version go1.23.3 linux/amd64
This tutorial is written and tested with Go version 1.22.2 on a Linux system.
Copying with ioutil
The first example uses the ioutil
package for a straightforward
approach. It reads the entire source file into memory and writes it to the
destination, ideal for small files due to its simplicity and minimal code.
package main import ( "io/ioutil" "log" ) func main() { src := "words.txt" dest := "words2.txt" bytesRead, err := ioutil.ReadFile(src) if err != nil { log.Fatal(err) } err = ioutil.WriteFile(dest, bytesRead, 0644) if err != nil { log.Fatal(err) } }
The ioutil.ReadFile
function reads the entire content of the source
file into a byte slice, handling file opening and closing internally. The
ioutil.WriteFile
function writes this byte slice to the destination
file, creating or overwriting it with the specified permissions (0644). This
method is concise but may not be suitable for very large files due to memory
usage.
Using io.Copy
The second example employs the io.Copy
function, which streams data
from the source to the destination file. This method is memory-efficient as it
avoids loading the entire file into memory, making it suitable for large files.
package main import ( "io" "log" "os" ) func main() { src := "words.txt" dst := "words2.txt" fin, err := os.Open(src) if err != nil { log.Fatal(err) } defer fin.Close() fout, err := os.Create(dst) if err != nil { log.Fatal(err) } defer fout.Close() _, err = io.Copy(fout, fin) if err != nil { log.Fatal(err) } }
We use os.Open
to open the source file and os.Create
to
create or truncate the destination file. These return file handles that are
passed to io.Copy
, which efficiently streams data in chunks. The
defer
statements ensure both files are closed after copying,
preventing resource leaks. This approach balances simplicity and performance.
Using File.Read and File.Write
The third example uses File.Read
and File.Write
for
manual control over the copying process. It reads the file in chunks, offering
flexibility to process data during copying, which is useful for custom
transformations or monitoring progress.
package main import ( "io" "log" "os" ) func main() { src := "words.txt" dst := "words2.txt" buf := make([]byte, 1024) fin, err := os.Open(src) if err != nil { log.Fatal(err) } defer fin.Close() fout, err := os.Create(dst) if err != nil { log.Fatal(err) } defer fout.Close() for { n, err := fin.Read(buf) if err != nil && err != io.EOF { log.Fatal(err) } if n == 0 { break } if _, err := fout.Write(buf[:n]); err != nil { log.Fatal(err) } } }
A 1024-byte buffer is created to read chunks of the source file using
File.Read
. The loop continues until no bytes are read (n == 0),
indicating the end of the file. Each chunk is written to the destination file
using File.Write
. The io.EOF
check distinguishes between
read errors and the end of the file. This method provides granular control but
requires more code.
Using os.ReadFine and os.WriteFile
The fourth example uses os.ReadFile
and os.WriteFile
,
modern replacements for the deprecated ioutil
functions. This
approach is similar to the first example but uses updated APIs, ensuring
compatibility with newer Go versions.
package main import ( "log" "os" ) func main() { src := "words.txt" dst := "words2.txt" data, err := os.ReadFile(src) if err != nil { log.Fatal(err) } err = os.WriteFile(dst, data, 0644) if err != nil { log.Fatal(err) } }
The os.ReadFile
function reads the entire source file into a byte
slice, similar to ioutil.ReadFile
. The os.WriteFile
function writes this data to the destination file with the specified permissions
(0644). This method is simple and recommended for small files in modern Go
programs, as it uses non-deprecated functions from the os
package.
Copying with io.CopyBuffer
The fifth example combines io.CopyBuffer
with a custom buffer,
offering a variation of the second example. It allows explicit control over the
buffer size, which can optimize performance for specific file sizes or hardware.
package main import ( "io" "log" "os" ) func main() { src := "words.txt" dst := "words2.txt" buf := make([]byte, 4096) fin, err := os.Open(src) if err != nil { log.Fatal(err) } defer fin.Close() fout, err := os.Create(dst) if err != nil { log.Fatal(err) } defer fout.Close() _, err = io.CopyBuffer(fout, fin, buf) if err != nil { log.Fatal(err) } }
We allocate a 4096-byte buffer for copying, larger than the default used by
io.Copy
. The io.CopyBuffer
function streams data from
the source to the destination file using this buffer. This method is efficient
for large files and allows tuning the buffer size for performance, while
maintaining the simplicity of the streaming approach.
Source
In this article we have copied files in Golang.
Author
List all Go tutorials.