Skip to content

Input and Output

go
package main

import "fmt"

func main() {
   fmt.Println("Hello 世界!")
}

The first introductory example on this site was outputting a string. This section explains how to perform input and output in Go.

File Descriptors

go
var (
   Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
   Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
   Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

In the os package, there are three externally exposed file descriptors, all of type *os.File:

  • os.Stdin - Standard Input
  • os.Stdout - Standard Output
  • os.Stderr - Standard Error

Input and output in Go are all done through these.

Output

There are many ways to output in Go. Here are some common ones:

stdout

Since standard output is itself a file, you can directly write strings to standard output:

go
package main

import "os"

func main() {
  os.Stdout.WriteString("hello world!")
}

print

Go has two built-in functions, print and println. They output parameters to standard error and are only used for debugging. They are generally not recommended.

go
package main

func main() {
  print("hello world!\n")
  println("hello world")
}

fmt

The most common usage is to use the fmt package. It provides the fmt.Println function, which outputs parameters to standard output by default.

go
package main

import "fmt"

func main() {
  fmt.Println("hello world!")
}

It accepts parameters of any type. If the type implements the String interface, it will call the String method to get its string representation. Therefore, the output is highly readable and suitable for most scenarios. However, since it uses reflection internally, it is not recommended for heavy use in performance-sensitive scenarios.

bufio

bufio provides buffered output methods. It first writes data to memory and outputs to the specified Writer when a certain threshold is reached. The default buffer size is 4KB. It is recommended to use this package for file I/O and network I/O.

go
func main() {
  writer := bufio.NewWriter(os.Stdout)
  defer writer.Flush()
  writer.WriteString("hello world!")
}

You can also combine it with the fmt package:

go
func main() {
  writer := bufio.NewWriter(os.Stdout)
  defer writer.Flush()
  fmt.Fprintln(writer, "hello world!")
}

Formatting

The formatted output functionality in Go is basically provided by the fmt.Printf function. If you have learned C-like languages, it will feel very familiar. Here is a simple example:

go
func main() {
  fmt.Printf("hello world, %s!", "jack")
}

Below are all the current format verbs in Go:

#FormatDescriptionAccepted Types
1%%Outputs a percent sign %Any
2%sOutputs string/[] byte valuestring,[] byte
3%qFormats string, output has double quotes "" around the stringstring,[] byte
4%dOutputs decimal integer valueInteger
5%fOutputs floating point numberFloating point
6%eOutputs in scientific notation, can also be used for complex numbersFloating point
7%ESame as %eFloating point
8%gDetermines whether to output %f or %e based on actual situation, removes extra zerosFloating point
9%bOutputs the binary representation of an integerNumeric
10%#bOutputs the full binary representationNumeric
11%oOutputs the octal representation of an integerInteger
12%#oOutputs the full octal representation of an integerInteger
13%xOutputs lowercase hexadecimal representation of an integerNumeric
14%#xOutputs the full lowercase hexadecimal representation of an integerNumeric
15%XOutputs uppercase hexadecimal representation of an integerNumeric
16%#XOutputs the full uppercase hexadecimal representation of an integerNumeric
17%vOutputs the original form of the value, mostly used for data structuresAny
18%+vOutputs struct with field namesAny
19%#vOutputs complete Go syntax format valueAny
20%tOutputs boolean valueBoolean
21%TOutputs the corresponding Go language type valueAny
22%cOutputs the character corresponding to the Unicode code pointint32
23%UOutputs the Unicode code point corresponding to the characterrune,byte
24%pOutputs the address pointed to by the pointerPointer

Use fmt.Sprintf or fmt.Printf to format strings or output formatted strings. Here are some examples:

go
fmt.Printf("%%%s\n", "hello world")

fmt.Printf("%s\n", "hello world")
fmt.Printf("%q\n", "hello world")
fmt.Printf("%d\n", 2<<7-1)

fmt.Printf("%f\n", 1e2)
fmt.Printf("%e\n", 1e2)
fmt.Printf("%E\n", 1e2)
fmt.Printf("%g\n", 1e2)

fmt.Printf("%b\n", 2<<7-1)
fmt.Printf("%#b\n", 2<<7-1)
fmt.Printf("%o\n", 2<<7-1)
fmt.Printf("%#o\n", 2<<7-1)
fmt.Printf("%x\n", 2<<7-1)
fmt.Printf("%#x\n", 2<<7-1)
fmt.Printf("%X\n", 2<<7-1)
fmt.Printf("%#X\n", 2<<7-1)

type person struct {
    name    string
    age     int
    address string
}
fmt.Printf("%v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%+v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%#v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%t\n", true)
fmt.Printf("%T\n", person{})
fmt.Printf("%c%c\n", 20050, 20051)
fmt.Printf("%U\n", '')
fmt.Printf("%p\n", &person{})

When using other bases, adding a space between % and the format verb can achieve the effect of a separator:

go
func main() {
  str := "abcdefg"
  fmt.Printf("%x\n", str)
  fmt.Printf("% x\n", str)
}

The output of this example is:

61626364656667
61 62 63 64 65 66 67

When using numbers, you can also automatically pad with zeros:

go
fmt.Printf("%09d", 1)
// 000000001

Same for binary:

go
fmt.Printf("%09b", 1<<3)
// 000001000

Error Cases

Number of format specifiers < number of arguments:

go
fmt.Printf("", "") //%!(EXTRA string=)

Number of format specifiers > number of arguments:

go
fmt.Printf("%s%s", "") //%!s(MISSING)

Type mismatch:

go
fmt.Printf("%s", 1) //%!s(int=1)

Missing format verb:

go
fmt.Printf("%", 1) // %!(NOVERB)%!(EXTRA int=1)

Input

Common input methods are introduced below:

read

You can read input content like reading a file directly:

go
func main() {
  var buf [1024]byte
  n, _ := os.Stdin.Read(buf[:])
  os.Stdout.Write(buf[:n])
}

This is too cumbersome to use and is generally not recommended.

fmt

We can use the functions provided by the fmt package, which are similar to C.

go
// Scans text read from os.Stdin, separated by whitespace, newlines are also treated as whitespace
func Scan(a ...any) (n int, err error)

// Similar to Scan, but stops scanning when encountering a newline
func Scanln(a ...any) (n int, err error)

// Scans according to a formatted string
func Scanf(format string, a ...any) (n int, err error)

Read two numbers:

go
func main() {
  var a, b int
  fmt.Scanln(&a, &b)
  fmt.Printf("%d + %d = %d\n", a, b, a+b)
}

Read a fixed-length array:

go
func main() {
  n := 10
  s := make([]int, n)
  for i := range n {
    fmt.Scan(&s[i])
  }
  fmt.Println(s)
}
1 2 3 4 5 6 7 8 9 10
[1 2 3 4 5 6 7 8 9 10]

bufio

When there is a large amount of input to read, it is recommended to use bufio.Reader for reading content:

go
func main() {
    reader := bufio.NewReader(os.Stdin)
    var a, b int
    fmt.Fscanln(reader, &a, &b)
    fmt.Printf("%d + %d = %d\n", a, b, a+b)
}

scanner

bufio.Scanner is similar to bufio.Reader, but it reads line by line.

go
func main() {
  scanner := bufio.NewScanner(os.Stdin)
  for scanner.Scan() {
    line := scanner.Text()
    if line == "exit" {
      break
    }
    fmt.Println("scan", line)
  }
}

The result is:

first line
scan first line
second line
scan second line
third line
scan third line
exit

TIP

For practicing input and output, you can go to Luogu and solve a few simple ACM-style algorithm problems to get familiar with it.

Golang by www.golangdev.cn edit