The official file operation standard library provided by Go is scattered in multiple packages such as OS and Ioutil, and there are many methods in it covering all the scenarios of file operation. However, there are not many scenarios that require direct file operation in my normal development process, and besides, it is difficult to search the documents of Go standard library. Every time I have to use a file function, I directly Google the corresponding function. By chance, I found a blog written by a foreign person in 2015. He summarized 30 file operation scenarios with common file functions, including four categories: basic operation, read and write operation, file compression and other operations. Code examples are given for each file operation. Write very good, so I translated the author’s article, strongly recommend you read it, browse its catalog, and then put in the favorites to eat ash…… You can refer to it in case you ever need it.

The original link: www.devdungeon.com/content/wor…

Author: NanoDano

The author homepage: www.devdungeon.com/users/nanod…

introduce

Everything is file

One of the fundamental designs of UNIX is “Everything is a file”. We don’t have to know what the device driver of the operating system maps to a file descriptor. The operating system provides an interface to the file format for the device.

The Reader and Writer interfaces in the Go language are similar. We simply read and write bytes without knowing where the reader’s data comes from or where writer sends the data. You can view available devices under /dev, some of which may require higher permissions to access.

Basic file operation

Creating an empty file

package main

import (
    "log"
    "os"
)

var (
    newFile *os.File
    err     error
)

func main(a) {
    newFile, err = os.Create("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    log.Println(newFile)
    newFile.Close()
}
Copy the code

Truncate Cuts the file

package main

import (
    "log"
    "os"
)

func main(a) {
    // Crop a file to 100 bytes.
    // If the file is originally less than 100 bytes, the original content of the file is preserved and the remaining bytes are filled with null bytes.
    // If the file originally exceeds 100 bytes, the excess bytes will be discarded.
    // So we always get the exact 100-byte file.
    // Passing 0 clears the file.

    err := os.Truncate("test.txt".100)
    iferr ! =nil {
        log.Fatal(err)
    }
}
Copy the code

Obtaining File Information

package main

import (
    "fmt"
    "log"
    "os"
)

var (
    fileInfo os.FileInfo
    err      error
)

func main(a) {
    // If the file does not exist, an error is returned
    fileInfo, err = os.Stat("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Println("File name:", fileInfo.Name())
    fmt.Println("Size in bytes:", fileInfo.Size())
    fmt.Println("Permissions:", fileInfo.Mode())
    fmt.Println("Last modified:", fileInfo.ModTime())
    fmt.Println("Is Directory: ", fileInfo.IsDir())
    fmt.Printf("System interface type: %T\n", fileInfo.Sys())
    fmt.Printf("System info: %+v\n\n", fileInfo.Sys())
}
Copy the code

Rename and move

package main

import (
    "log"
    "os"
)

func main(a) {
    originalPath := "test.txt"
    newPath := "test2.txt"
    err := os.Rename(originalPath, newPath)
    iferr ! =nil {
        log.Fatal(err)
    }
}
Copy the code

Delete the file

package main

import (
    "log"
    "os"
)

func main(a) {
    err := os.Remove("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
}
Copy the code

Open and close files

package main

import (
    "log"
    "os"
)

func main(a) {
    // Simply open it in read-only mode. The following examples cover reading and writing examples.
    file, err := os.Open("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    file.Close()

    OpenFile provides more options.
    // The last parameter is permission mode
    // The second is the open property
    file, err = os.OpenFile("test.txt", os.O_APPEND, 0666)
    iferr ! =nil {
        log.Fatal(err)
    }
    file.Close()

    // The following attributes can be used individually or in combination.
    // The second parameter of OpenFile can be set with the OR operation, for example:
    // os.O_CREATE|os.O_APPEND
    / / or OS. O_CREATE | OS. O_TRUNC. | OS O_WRONLY

    // os.o_rdonly // Read-only
    // os.o_wronly // Write only
    // os.o_rdwr // Read and write
    // O_APPEND // Add (Append) to file
    O_CREATE // If the file does not exist, create it first
    // O_TRUNC // Crop the file when the file is opened
    O_EXCL // When used with O_CREATE, the file cannot exist
    O_SYNC // To synchronize I/O
}
Copy the code

Check whether the file exists

package main

import (
    "log"
    "os"
)

var (
    fileInfo *os.FileInfo
    err      error
)

func main(a) {
    // Error is returned if the file does not exist
    fileInfo, err := os.Stat("test.txt")
    iferr ! =nil {
        if os.IsNotExist(err) {
            log.Fatal("File does not exist.")
        }
    }
    log.Println("File does exist. File information:")
    log.Println(fileInfo)
}
Copy the code

Checking read and write Permissions

package main

import (
    "log"
    "os"
)

func main(a) {
    // This example tests write permission and returns error if there is no write permission.
    // If the file does not exist, an error message will be returned.
    file, err := os.OpenFile("test.txt", os.O_WRONLY, 0666)
    iferr ! =nil {
        if os.IsPermission(err) {
            log.Println("Error: Write permission denied.")
        }
    }
    file.Close()

    // Test read permissions
    file, err = os.OpenFile("test.txt", os.O_RDONLY, 0666)
    iferr ! =nil {
        if os.IsPermission(err) {
            log.Println("Error: Read permission denied.")
        }
    }
    file.Close()
}
Copy the code

Change permission, owner, and timestamp

package main

import (
    "log"
    "os"
    "time"
)

func main(a) {
    // Change file permissions in Linux style
    err := os.Chmod("test.txt".0777)
    iferr ! =nil {
        log.Println(err)
    }

    // Change the file owner
    err = os.Chown("test.txt", os.Getuid(), os.Getgid())
    iferr ! =nil {
        log.Println(err)
    }

    // Change the timestamp
    twoDaysFromNow := time.Now().Add(48 * time.Hour)
    lastAccessTime := twoDaysFromNow
    lastModifyTime := twoDaysFromNow
    err = os.Chtimes("test.txt", lastAccessTime, lastModifyTime)
    iferr ! =nil {
        log.Println(err)
    }
}
Copy the code

Create hard and soft links

A normal file is a place that points to the hard disk’s inode. Hard links create a new pointer to the same place. Files will not be deleted until all links have been removed. Hard links work only on the same file system. You can think of a hard link as a normal link.

Symbolic link, also known as a soft link, is a bit different from a hard link because it does not directly point to the same place on the hard disk, but instead refers to other files by name. They can point to different files on different file systems. Not all operating systems support soft links.

package main

import (
    "os"
    "log"
    "fmt"
)

func main(a) {
    // Create a hard link.
    // The same file content will have two names after creation. Changing the content of one file will affect the other.
    // Deleting and renaming do not affect the other.
    err := os.Link("original.txt"."original_also.txt")
    iferr ! =nil {
        log.Fatal(err)
    }

    fmt.Println("creating sym")
    // Create a symlink
    err = os.Symlink("original.txt"."original_sym.txt")
    iferr ! =nil {
        log.Fatal(err)
    }

    // Lstat returns information about a file, but when the file is a soft link, it returns information about the soft link, not the referenced file.
    // Symlink does not work on Windows.
    fileInfo, err := os.Lstat("original_sym.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Printf("Link info: %+v", fileInfo)

    // Changing the owner of the soft link does not affect the original file.
    err = os.Lchown("original_sym.txt", os.Getuid(), os.Getgid())
    iferr ! =nil {
        log.Fatal(err)
    }
}
Copy the code

File to read and write

Copy the file

package main

import (
    "os"
    "log"
    "io"
)

func main(a) {
    // Open the original file
    originalFile, err := os.Open("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    defer originalFile.Close()

    // Create a new file as the target file
    newFile, err := os.Create("test_copy.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    defer newFile.Close()

    // Copy bytes from the source to the target file
    bytesWritten, err := io.Copy(newFile, originalFile)
    iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Copied %d bytes.", bytesWritten)

    // Flush the file contents to the hard disk
    err = newFile.Sync()
    iferr ! =nil {
        log.Fatal(err)
    }
}
Copy the code

Jump to the specified location of the file (Seek)

package main

import (
    "os"
    "fmt"
    "log"
)

func main(a) {
    file, _ := os.Open("test.txt")
    defer file.Close()

    // The deviation can be positive or negative
    var offset int64 = 5

    // Calculate the initial position of offset
    // 0 = file start position
    // 1 = current position
    // 2 = end of file
    var whence int = 0
    newPosition, err := file.Seek(offset, whence)
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Println("Just moved to 5:", newPosition)

    // Roll back two bytes from the current position
    newPosition, err = file.Seek(2 -.1)
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Println("Just moved back two:", newPosition)

    // Use the following technique to get the current position
    currentPosition, err := file.Seek(0.1)
    fmt.Println("Current position:", currentPosition)

    // Go to the beginning of the file
    newPosition, err = file.Seek(0.0)
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Println("The Position after seeking 0, 0,", newPosition)
}
Copy the code

Write files

You can write to an open file using the OS package. Because Go executables are statically linked executables, each package you import increases the size of your executable. Other packages like IO, ‘ioutil’, and ‘bufio’ provide some methods, but they are not required.

package main

import (
    "os"
    "log"
)

func main(a) {
    // Open the file in writable mode
    file, err := os.OpenFile(
        "test.txt",
        os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
        0666.)iferr ! =nil {
        log.Fatal(err)
    }
    defer file.Close()

    // Write the section to the file
    byteSlice := []byte("Bytes! \n")
    bytesWritten, err := file.Write(byteSlice)
    iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Wrote %d bytes.\n", bytesWritten)
}
Copy the code

Fast write files

The ioutil package has a very useful method, WriteFile(), that handles creating or opening files, writing byte slices, and closing files. You can use it if you need to write sections neatly and quickly into a file.

package main

import (
    "io/ioutil"
    "log"
)

func main(a) {
    err := ioutil.WriteFile("test.txt"And []byte("Hi\n"), 0666)
    iferr ! =nil {
        log.Fatal(err)
    }
}
Copy the code

Write using cache

The Bufio package provides writer with caching, so you can use memory caching before writing to hard disk. This is useful when you’re dealing with a lot of data, as it can save you time on operating hard disk I/O. It is also useful in other situations, such as when you write one byte at a time, storing it in memory cache, and then writing it to hard disk at a time to reduce disk wear and improve performance.

package main

import (
    "log"
    "os"
    "bufio"
)

func main(a) {
    // Open the file and just write
    file, err := os.OpenFile("test.txt", os.O_WRONLY, 0666)
    iferr ! =nil {
        log.Fatal(err)
    }
    defer file.Close()

    // Create buffered Writer for this file
    bufferedWriter := bufio.NewWriter(file)

    // Write to buffer
    bytesWritten, err := bufferedWriter.Write(
        []byte{65.66.67},)iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Bytes written: %d\n", bytesWritten)

    // Write a string to buffer
    // You can also use WriteRune() and WriteByte()
    bytesWritten, err = bufferedWriter.WriteString(
        "Buffered string\n".)iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Bytes written: %d\n", bytesWritten)

    // Check the number of bytes in the cache
    unflushedBufferSize := bufferedWriter.Buffered()
    log.Printf("Bytes buffered: %d\n", unflushedBufferSize)

    // How many bytes are available (unused cache size)
    bytesAvailable := bufferedWriter.Available()
    iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Available buffer: %d\n", bytesAvailable)

    // Write memory buffer to disk
    bufferedWriter.Flush()

    // Discards cached content that has not yet been flushed, clearing the error and passing its output to writer in the argument
    // This is useful when you want to pass the cache to another writer
    bufferedWriter.Reset(bufferedWriter)

    bytesAvailable = bufferedWriter.Available()
    iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Available buffer: %d\n", bytesAvailable)

    // Resize the cache.
    // The first argument is where the cache should be output to. In this example we use the same writer.
    // If we set the new size to be smaller than the cache size of the first argument writer, such as 10, we do not get a cache size of 10 bytes,
    // It is the cache of writer's original size, which defaults to 4096.
    // Its function is mainly for expansion.
    bufferedWriter = bufio.NewWriterSize(
        bufferedWriter,
        8000.)// check the size of the cache after resize
    bytesAvailable = bufferedWriter.Available()
    iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Available buffer: %d\n", bytesAvailable)
}
Copy the code

Read up to N bytes

Os.file provides the basic functionality for File manipulation, while IO, ioutil, and bufio provide additional helper functions.

package main

import (
    "os"
    "log"
)

func main(a) {
    // Open the file, read only
    file, err := os.Open("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    defer file.Close()

    // Read len(b) bytes from the file.
    // Returning 0 bytes means the end of the file has been read
    IO.EOF error is returned when a file is read
    byteSlice := make([]byte.16)
    bytesRead, err := file.Read(byteSlice)
    iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Number of bytes read: %d\n", bytesRead)
    log.Printf("Data read: %s\n", byteSlice)
}
Copy the code

Read N bytes

package main

import (
    "os"
    "log"
    "io"
)

func main(a) {
    // Open file for reading
    file, err := os.Open("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }

    // file.read () can Read a small file into a large byte slice,
    Io.readfull () returns an error if the file's number of bytes is less than the number of byte slice bytes
    byteSlice := make([]byte.2)
    numBytesRead, err := io.ReadFull(file, byteSlice)
    iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Number of bytes read: %d\n", numBytesRead)
    log.Printf("Data read: %s\n", byteSlice)
}
Copy the code

Read at least N bytes

package main

import (
    "os"
    "log"
    "io"
)

func main(a) {
    // Open the file, read only
    file, err := os.Open("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }

    byteSlice := make([]byte.512)
    minBytes := 8
    // io.readatleast () returns an error if the smallest byte cannot be retrieved, but keeps the read file
    numBytesRead, err := io.ReadAtLeast(file, byteSlice, minBytes)
    iferr ! =nil {
        log.Fatal(err)
    }
    log.Printf("Number of bytes read: %d\n", numBytesRead)
    log.Printf("Data read: %s\n", byteSlice)
}
Copy the code

Read all bytes

package main

import (
    "os"
    "log"
    "fmt"
    "io/ioutil"
)

func main(a) {
    file, err := os.Open("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }

    / / OS. The File. The Read (), IO. ReadFull () and
    // io.readatleast () requires a fixed size byte slice before reading.
    // But ioutil.readall () reads every byte of reader(file in this case) and then slices the byte back.
    data, err := ioutil.ReadAll(file)
    iferr ! =nil {
        log.Fatal(err)
    }

    fmt.Printf("Data as hex: %x\n", data)
    fmt.Printf("Data as string: %s\n", data)
    fmt.Println("Number of bytes read:".len(data))
}
Copy the code

Fast read to memory

package main

import (
    "log"
    "io/ioutil"
)

func main(a) {
    // Read the file into byte slice
    data, err := ioutil.ReadFile("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }

    log.Printf("Data read: %s\n", data)
}
Copy the code

Using cache read

There are cached writes and cached reads. The cache Reader will cache something in memory. It provides more functions than os.file and io.reader, with a default cache size of 4096 and a minimum cache size of 16.

package main

import (
    "os"
    "log"
    "bufio"
    "fmt"
)

func main(a) {
    // Open the file and create a buffered Reader
    file, err := os.Open("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    bufferedReader := bufio.NewReader(file)

    // Get bytes, current pointer unchanged
    byteSlice := make([]byte.5)
    byteSlice, err = bufferedReader.Peek(5)
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Printf("Peeked at 5 bytes: %s\n", byteSlice)

    // The pointer moves simultaneously
    numBytesRead, err := bufferedReader.Read(byteSlice)
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Printf("Read %d bytes: %s\n", numBytesRead, byteSlice)

    // Read a byte, Error is returned if the read is unsuccessful
    myByte, err := bufferedReader.ReadByte()
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Printf("Read 1 byte: %c\n", myByte)     

    // The delimiter is read, containing the delimiter, and returns byte slice
    dataBytes, err := bufferedReader.ReadBytes('\n')
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Printf("Read bytes: %s\n", dataBytes)           

    // Reads delimiter, contains delimiter, returns string
    dataString, err := bufferedReader.ReadString('\n')
    iferr ! =nil {
        log.Fatal(err)
    }
    fmt.Printf("Read string: %s\n", dataString)     

    // This example reads a lot of lines, so test.txt should contain more than one line of text to avoid errors
}
Copy the code

Using scanner

Scanner is a type under the Bufio package and is useful when dealing with delimited text in files. Usually we use a newline as a separator to split the contents of a file into multiple lines. In CSV files, commas are used as delimiters. The os.file File can be wrapped as bufio.scanner, which acts like a cache reader. We call the Scan() method to read the next delimiter and use Text() or Bytes() to get the read data.

The delimiter may not be a simple byte or character, but there is a special way to perform the function of the delimiter, how much to move the pointer, and what data to return. If there is no custom SplitFunc, the default ScanLines will use the newline character as the delimiter. Other delimiter functions include ScanRunes and ScanWords, which are included in the Bufio package.

// To define your own split function, match this fingerprint
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

// Returning (0, nil, nil) will tell the scanner
// to scan again, but with a bigger buffer because
// it wasn't enough data to reach the delimiter
Copy the code

In the following example, bufio.scanner is created for a file and is read word by word:

package main

import (
    "os"
    "log"
    "fmt"
    "bufio"
)

func main(a) {
    file, err := os.Open("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    scanner := bufio.NewScanner(file)

    // The default separator function is bufio.scanlines, we use ScanWords here.
    // You can also customize a split function of type SplitFunc
    scanner.Split(bufio.ScanWords)

    // Scan the next token.
    success := scanner.Scan()
    if success == false {
        // An Error occurs or EOF returns Error
        err = scanner.Err()
        if err == nil {
            log.Println("Scan completed and reached EOF")}else {
            log.Fatal(err)
        }
    }

    // Get data, Bytes() or Text()
    fmt.Println("First word found:", scanner.Text())

    // Call scanner.scan () again to find the next token
}
Copy the code

File compression

Package (ZIP) files

// This example uses zip but standard library
// also supports tar archives
package main

import (
    "archive/zip"
    "log"
    "os"
)

func main(a) {
    // Create a package file
    outFile, err := os.Create("test.zip")
    iferr ! =nil {
        log.Fatal(err)
    }
    defer outFile.Close()

    // Create zip writer
    zipWriter := zip.NewWriter(outFile)


    // Write files to the package file.
    // Here we use hard-coded content. You can walk through a folder and write the files and their contents into the package file.
    var filesToArchive = []struct {
        Name, Body string} {{"test.txt"."String contents of file"},
        {"test2.txt"."\x61\x62\x63\n"}},// Write the following contents to the package file, one by one.
    for _, file := range filesToArchive {
            fileWriter, err := zipWriter.Create(file.Name)
            iferr ! =nil {
                    log.Fatal(err)
            }
            _, err = fileWriter.Write([]byte(file.Body))
            iferr ! =nil {
                    log.Fatal(err)
            }
    }

    / / clean up
    err = zipWriter.Close()
    iferr ! =nil {
            log.Fatal(err)
    }
}
Copy the code

Extract (unzip) files

// This example uses zip but standard library
// also supports tar archives
package main

import (
    "archive/zip"
    "log"
    "io"
    "os"
    "path/filepath"
)

func main(a) {
    zipReader, err := zip.OpenReader("test.zip")
    iferr ! =nil {
        log.Fatal(err)
    }
    defer zipReader.Close()

    // Walk through each file/folder in the package file
    for _, file := range zipReader.Reader.File {
        // The file in the package file is just like a normal file object
        zippedFile, err := file.Open()
        iferr ! =nil {
            log.Fatal(err)
        }
        defer zippedFile.Close()

        // Specify the name of the extracted file.
        // You can specify the full pathname or a prefix so that they can be placed in different folders.
        // Our example uses the same filename as in the package file.
        targetDir := ". /"
        extractedFilePath := filepath.Join(
            targetDir,
            file.Name,
        )

        // Extract projects or create folders
        if file.FileInfo().IsDir() {
            // Create a folder and set the same permissions
            log.Println("Creating directory:", extractedFilePath)
            os.MkdirAll(extractedFilePath, file.Mode())
        } else {
            // Extract normal files
            log.Println("Extracting file:", file.Name)

            outputFile, err := os.OpenFile(
                extractedFilePath,
                os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
                file.Mode(),
            )
            iferr ! =nil {
                log.Fatal(err)
            }
            defer outputFile.Close()

            Copy copies the contents of a file succinctly with IO
            _, err = io.Copy(outputFile, zippedFile)
            iferr ! =nil {
                log.Fatal(err)
            }
        }
    }
}
Copy the code

The compressed file

The standard library also supports zlib, bz2, flate, and LZW
package main

import (
    "os"
    "compress/gzip"
    "log"
)

func main(a) {
    outputFile, err := os.Create("test.txt.gz")
    iferr ! =nil {
        log.Fatal(err)
    }

    gzipWriter := gzip.NewWriter(outputFile)
    defer gzipWriter.Close()

    // When we write data to gizp Writer, it compresses the data in turn and writes it to the underlying file.
    // We don't have to worry about how it is compressed, or just operate like a normal writer.
    _, err = gzipWriter.Write([]byte("Gophers rule! \n"))
    iferr ! =nil {
        log.Fatal(err)
    }

    log.Println("Compressed data written to file.")}Copy the code

Unzip file

The standard library also supports zlib, bz2, flate, and LZW
package main

import (
    "compress/gzip"
    "log"
    "io"
    "os"
)

func main(a) {
    // Open a gzip file.
    // The file is a reader, but we can use various data sources, such as the Gzipped content returned by the Web server,
    // Its contents are not a file, but a memory stream
    gzipFile, err := os.Open("test.txt.gz")
    iferr ! =nil {
        log.Fatal(err)
    }

    gzipReader, err := gzip.NewReader(gzipFile)
    iferr ! =nil {
        log.Fatal(err)
    }
    defer gzipReader.Close()

    // Unzip to a writer, which is a file writer
    outfileWriter, err := os.Create("unzipped.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    defer outfileWriter.Close()

    // Copy the content
    _, err = io.Copy(outfileWriter, gzipReader)
    iferr ! =nil {
        log.Fatal(err)
    }
}
Copy the code

Other file operations

Temporary files and directories

Ioutil provides two functions: TempDir() and TempFile(). When finished, the caller is responsible for deleting these temporary files and folders. The nice thing is that when you pass an empty string as a folder name, it creates these items in a temporary folder of the operating system (/ TMP on Linux). Os.tempdir () returns the temporary folder of the current operating system.

package main

import (
     "os"
     "io/ioutil"
     "log"
     "fmt"
)

func main(a) {
     // Create a temporary folder in the system temporary folder
     tempDirPath, err := ioutil.TempDir(""."myTempDir")
     iferr ! =nil {
          log.Fatal(err)
     }
     fmt.Println("Temp dir created:", tempDirPath)

     // Create temporary files in temporary folder
     tempFile, err := ioutil.TempFile(tempDirPath, "myTempFile.txt")
     iferr ! =nil {
          log.Fatal(err)
     }
     fmt.Println("Temp file created:", tempFile.Name())

     / /... Do some operations...

     // Close the file
     err = tempFile.Close()
     iferr ! =nil {
        log.Fatal(err)
    }

    // Delete the resource we created
     err = os.Remove(tempFile.Name())
     iferr ! =nil {
        log.Fatal(err)
    }
     err = os.Remove(tempDirPath)
     iferr ! =nil {
        log.Fatal(err)
    }
}
Copy the code

Download files over HTTP

package main

import (
     "os"
     "io"
     "log"
     "net/http"
)

func main(a) {
     newFile, err := os.Create("devdungeon.html")
     iferr ! =nil {
          log.Fatal(err)
     }
     defer newFile.Close()

     url := "http://www.devdungeon.com/archive"
     response, err := http.Get(url)
     defer response.Body.Close()

     // Write the contents of the HTTP Response Body to the file
     // Body satisfies the reader interface, so we can use ioutil.copy
     numBytesWritten, err := io.Copy(newFile, response.Body)
     iferr ! =nil {
          log.Fatal(err)
     }
     log.Printf("Downloaded %d byte file.\n", numBytesWritten)
}
Copy the code

Hash and digest

package main

import (
    "crypto/md5"
    "crypto/sha1"
    "crypto/sha256"
    "crypto/sha512"
    "log"
    "fmt"
    "io/ioutil"
)

func main(a) {
    // Get the file contents
    data, err := ioutil.ReadFile("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }

    / / calculate the Hash
    fmt.Printf("Md5: %x\n\n", md5.Sum(data))
    fmt.Printf("Sha1: %x\n\n", sha1.Sum(data))
    fmt.Printf("Sha256: %x\n\n", sha256.Sum256(data))
    fmt.Printf("Sha512: %x\n\n", sha512.Sum512(data))
}
Copy the code

The above example copies the entire contents of the file into memory and passes it to the hash function. Another way is to create a Hash Writer and pass data to it using Write, WriteString, and Copy. The following example uses MD5 hashes, but you can use other writers.

package main

import (
    "crypto/md5"
    "log"
    "fmt"
    "io"
    "os"
)

func main(a) {
    file, err := os.Open("test.txt")
    iferr ! =nil {
        log.Fatal(err)
    }
    defer file.Close()

    // Create a new hasher that satisfies the Writer interface
    hasher := md5.New()
    _, err = io.Copy(hasher, file)
    iferr ! =nil {
        log.Fatal(err)
    }

    // Computes the hash and prints the result.
    // Pass nil as an argument, because we don't pass data as arguments, but through the Writer interface.
    sum := hasher.Sum(nil)
    fmt.Printf("Md5 checksum: %x\n", sum)
}
Copy the code

If you like my article, please give me a thumbs up. I will share what I have learned and seen and first-hand experience through technical articles every week. Thank you for your support. Wechat search public account “NMS bi Bi” to get my article push in the first time.