One of the most widely used packages for IO is fmt
(https://golang.org/pkg/fmt). It comes with an amalgam of functions designed for formatted input and output. The most common usage of the fmt
package is for writing to standard output and reading from standard input. This section also highlights other functions that make fmt
a great tool for IO.
The fmt
package offers several functions designed to write text data to arbitrary implementations of io.Writer. The fmt.Fprint
and fmt.Fprintln
functions write text with the default format while fmt.Fprintf
supports format specifiers. The following code snippet writes a columnar formatted list of metalloid
data to a specified text file using the fmt.Fprintf
function:
type metalloid struct { name string number int32 weight float64 } func main() { var metalloids = []metalloid{ {"Boron", 5, 10.81}, ... {"Polonium", 84, 209.0}, } file, _ := os.Create("./metalloids.txt") defer file.Close() for _, m := range metalloids { fmt.Fprintf( file, "%-10s %-10d %-10.3f ", m.name, m.number, m.weight, ) } }
golang.fyi/ch10/fmtfprint0.go
In the previous example, the fmt.Fprintf
function uses format specifiers to write formatted text to the io.File file
variable. The fmt.Fprintf
function supports a large number of format specifiers whose proper treatment is beyond the scope of this text. Refer to the online documentation for complete coverage of these specifiers.
The fmt.Print
, fmt.Printf
, and fmt.Println
have the exact same characteristics as the previous Fprint
-series of functions seen earlier. Instead of an arbitrary io.Writer
however, they write text to the standard output file handle os.Stdout
(see the section Standard output, input, and error covered earlier).
The following abbreviated code snippet shows an updated version of the previous example that writes the list of metalloids to a standard output instead of a regular file. Note that it is the same code except for the use of the fmt.Printf
instead of the fmt.Fprintf
function:
type metalloid struct { ... } func main() { var metalloids = []metalloid{ {"Boron", 5, 10.81}, ... {"Polonium", 84, 209.0}, } for _, m := range metalloids { fmt.Printf( "%-10s %-10d %-10.3f ", m.name, m.number, m.weight, ) } }
golang.fyi/ch10/fmtprint0.go
The fmt
package also supports formatted reading of textual data from io.Reader
interfaces. The fmt.Fscan
and fmt.Fscanln
functions can be used to read multiple values, separated by spaces, into specified parameters. The fmt.Fscanf
function supports format specifiers for a richer and flexible parsing of data input from io.Reader
implementations.
The following abbreviated code snippet uses the function fmt.Fscanf
for the formatted input of a space-delimited file (planets.txt
) containing planetary data:
func main() { var name, hasRing string var diam, moons int // read data data, err := os.Open("./planets.txt") if err != nil { fmt.Println("Unable to open planet data:", err) return } defer data.Close() for { _, err := fmt.Fscanf( data, "%s %d %d %s ", &name, &diam, &moons, &hasRing, ) if err != nil { if err == io.EOF { break } else { fmt.Println("Scan error:", err) return } } fmt.Printf( "%-10s %-10d %-6d %-6s ", name, diam, moons, hasRing, ) }
golang.fyi/ch10/fmtfscan0.go
The code reads from the io.File
variable data
, until it encounters an io.EOF
error indicating the end of the file. Each line of text it reads is parsed using format specifiers "%s %d %d %s
"
which matches the space-delimited layout of the records stored in the file. Each parsed token is then assigned to its respective variable name
, diam
, moons
, and hasRing,
which are printed to the standard output using the fm.Printf
function.
Instead of reading from an arbitrary io.Reader
, the fmt.Scan
, fmt.Scanf
, and fmt.Scanln
are used to read data from standard input file handle, os.Stdin
. The following code snippet shows a simple program that reads text input from the console:
func main() { var choice int fmt.Println("A square is what?") fmt.Print("Enter 1=quadrilateral 2=rectagonal:") n, err := fmt.Scanf("%d", &choice) if n != 1 || err != nil { fmt.Println("Follow directions!") return } if choice == 1 { fmt.Println("You are correct!") } else { fmt.Println("Wrong, Google it.") } }
golang.fyi/ch10/fmtscan1.go
In the previous program, the fmt.Scanf
function parses the input using the format specifier "%d"
to read an integer value from the standard input. The function will throw an error if the value read does not match exactly the specified format. For instance, the following shows what happens when character D
is read instead of an integer:
$> go run fmtscan1.go A square is what? Enter 1=quadrilateral 2=rectagonal: D Follow directions!
18.226.88.110