SoFunction
Updated on 2025-03-03

Summary of how to read files in Go language

When writing programs, you often need to read data from one file and then output it to another file. The most typical example is to read from stdin and output to stdout. go provides several ways to read files, let's take a look one by one~

func fmtScan() {
    str := ""
    for {
        (&str)
        ("[]: %q (%d)\n", str, len(str))
    }
}
// input: abc def ghi
// output:
//[]: "abc" (3)
//[]: "def" (3)
//[]: "ghi" (3)

Read data from stdin and output to memory variables. It will use the whitespace character as a split character character, and assign the divided string to the passed parameters in turn. In the above example, it is a cycle that is assigned to str three times respectively.

func osStdinRead() {
    p := make([]byte, 5)
    for {
        nn, err := (p)
        if err != nil && err !=  {
            panic(err)
        }
        ("[]: %q (%d)\n", p, nn)
        p = make([]byte, 5) // Clear p    }
}
// input: abcdefghijk
// output:
//[]: "abcde" (5)
//[]: "fghij" (5)
//[]: "k\n\x00\x00\x00" (2)

Read up to len(p) size data. If the input content exceeds len(p), Read will continue to read in the next loop.

io series

ReadAll

func ioReadAll() {
    for {
        p, err := ()
        if err != nil {
            panic(err)
        }
        ("[]: %q (%d)\n", p, len(p))
    }
}

// input: abc\nEOF
// output: []: "abc\n" (4)

ReadAll Reads everything and does not return EOF as an error.

ReadFull

func ioReadFull() {
    p := make([]byte, 5)
    for {
        nn, err := (, p)
        if err != nil && err !=  {
            ("[]: %q (%d)\n", p, nn)
            panic(err)
        }
        ("[]: %q (%d)\n", p, nn)
        p = make([]byte, 5)
    }
}

// input: aaaaaa
// output: []: "aaaaa" (5)

// input: aa\n\x00
// output: []: "aa\n\x00\x00" (3)

The goal of ReadFull is to fill p, which means that under normal circumstances, only the read data length nn==len(p) will be returned. There are two situations to note here:

  • No data to be read, ReadFull returns (0, EOF)
  • There is some data that is readable, but I encountered EOF before filling p, ReadFull returns (read length, ErrUnexpectedEOF)

bufio series

Bufio provides a buffer for io operations, avoiding access to disk every time.

Read

func bufioRead() {
    br := ()
    p := make([]byte, 5)
    for {
        nn, err := (p)
        if err != nil && err != {
            panic(err)
        }
        ("[]: %q (%d)\n", p, nn)
    }
}

// input: abcdefghijk
// output:
//[]: "abcde" (5)
//[]: "fghij" (5)
//[]: "k\n\x00\x00\x00" (2)

Read up to len(p) size data. If the input content exceeds len(p), Read will continue to read in the next loop.

ReadBytes

func bufioReadBytes() {
    br := ()
    for {
        p, err := ('\n')
        if err != nil && err != {
            panic(err)
        }
        ("[]: %q (%d)\n", p, len(p))
    }
}
// input: abcdef
// output: []: "abcdef\n" (7)

ReadBytes reads until the given delimiter is encountered, here is '\n' (the returned p contains \n). If err is encountered before reading the delimiter, the read data and err (usually EOF) are returned.

ReadString

func bufioReadString() {
    br := ()
    for {
        str, err := ('\n')
        if err != nil && err !=  {
            panic(err)
        }
        ("[]: %q (%d)\n", str, len(str))
    }
}

// input: abcdef
// output: []: "abcdef\n" (7)

ReadString is similar to ReadBytes, both of which do not return until the delimiter is read.

ReadRune

func bufioReadRune() {
    br := ()
    for {
        r, sz, err := ()
        if err != nil && err !=  {
            panic(err)
        }
        ("[]: %q (%d)\n", r, sz)
    }
}

// input: abc
// output: 
//[]: 'a' (1)
//[]: 'b' (1)
//[]: 'c' (1)
//[]: '\n' (1)

ReadRune Reads one UTF8 character at a time.

Scan

func bufioScan() {
    scanner := ()
    for () {
        text := ()
        ("[]: %q (%d)\n", text, len(text))
    }
    if () != nil {
        (().Error())
    }
}

Scan scans the file to the next token and returns true, and the token can then be read through Text, Bytes. When the scan stops, Scan returns false, and the error can be obtained through Err. If the scan stops because of EOF, Err=nil.

When creating scanner, ScanLines is used by default as the split function. It splits the input text into a series of lines, each line as a token. In addition, there are other segmentation functions:

  • ScanLines(Default): Split by line.
  • ScanWords: Words divided by whitespace characters.
  • ScanBytes: Split by bytes.
  • ScanRunes: Segmented according to UTF-8 encoded characters.

Summarize

If you just read it from stdin, it is short enough and easy to use. When the file is large, it feels not very flexible when using it. It is recommended to use a series of methods of bufio.

This is the end of this article about how to read files in Go language. For more related Go files, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!