Golang fmt.Fscanf function
last modified May 8, 2025
This tutorial explains how to use the fmt.Fscanf
function in Go.
We'll cover input parsing basics with practical examples of formatted scanning.
The fmt.Fscanf function scans input from a reader according to a format specifier. It parses values separated by whitespace into variables. This is useful for reading structured data from files or other input sources.
In Go, fmt.Fscanf
is similar to fmt.Scanf
but works
with any io.Reader
instead of standard input. It returns the number
of items successfully scanned and any error encountered.
Basic Fscanf example
The simplest use of fmt.Fscanf
reads values from a string reader.
This example demonstrates basic formatted scanning.
Note: The format string must match the input structure exactly.
package main import ( "fmt" "strings" ) func main() { input := "John 25 50000.50" reader := strings.NewReader(input) var name string var age int var salary float64 n, err := fmt.Fscanf(reader, "%s %d %f", &name, &age, &salary) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("Scanned %d items: %s, %d, %.2f\n", n, name, age, salary) }
The code reads a string, integer, and float from the input. The format string specifies the expected types, and variables must be passed as pointers.
Reading from a file
fmt.Fscanf
is commonly used to read structured data from files.
This example shows how to parse data from a text file.
package main import ( "fmt" "os" ) func main() { file, err := os.Open("data.txt") if err != nil { fmt.Println("Error opening file:", err) return } defer file.Close() var id int var product string var price float64 for { n, err := fmt.Fscanf(file, "%d %s %f\n", &id, &product, &price) if err != nil { break } fmt.Printf("Read %d items: %d %s %.2f\n", n, id, product, price) } }
The code reads multiple records from a file in a loop. Each line contains an integer, string, and float value separated by spaces.
Handling different formats
fmt.Fscanf
can parse various input formats. This example shows
different format specifiers in action.
package main import ( "fmt" "strings" ) func main() { input := "Date: 2023-05-15 Time: 14:30 Value: 42.7%" reader := strings.NewReader(input) var year, month, day, hour, minute int var value float64 var unit string n, err := fmt.Fscanf(reader, "Date: %d-%d-%d Time: %d:%d Value: %f%%%s", &year, &month, &day, &hour, &minute, &value, &unit) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("Scanned %d items: %d-%02d-%02d %02d:%02d %.1f%%\n", n, year, month, day, hour, minute, value) }
The format string includes literal text that must match the input exactly. Special characters like % must be escaped with another % in the format.
Reading multiple lines
fmt.Fscanf
can process multi-line input by including newlines in
the format string. This example demonstrates multi-line parsing.
package main import ( "fmt" "strings" ) func main() { input := `Person: Name: Alice Age: 30 Occupation: Engineer ` reader := strings.NewReader(input) var name, occupation string var age int _, err := fmt.Fscanf(reader, `Person: Name: %s Age: %d Occupation: %s `, &name, &age, &occupation) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("%s is a %d-year-old %s\n", name, age, occupation) }
The format string includes newlines to match the input structure. Backticks are used for raw string literals to preserve the formatting.
Error handling
Proper error handling is crucial when using fmt.Fscanf
. This
example shows how to handle various scanning errors.
package main import ( "fmt" "strings" ) func main() { tests := []string{ "100 200", // OK "100 abc", // type mismatch "100", // not enough values "100 200 300", // extra values } for _, input := range tests { reader := strings.NewReader(input) var a, b int n, err := fmt.Fscanf(reader, "%d %d", &a, &b) fmt.Printf("Input: %q\n", input) fmt.Printf("Scanned %d items: %d, %d\n", n, a, b) if err != nil { fmt.Println("Error:", err) } fmt.Println("-----") } }
The code tests different error scenarios. fmt.Fscanf
returns
the number of successfully scanned items and any error encountered.
Reading into a struct
fmt.Fscanf
can populate struct fields directly. This example
shows structured data parsing.
package main import ( "fmt" "strings" ) type Employee struct { ID int Name string Salary float64 } func main() { input := "101 Bob 75000.50" reader := strings.NewReader(input) var emp Employee n, err := fmt.Fscanf(reader, "%d %s %f", &emp.ID, &emp.Name, &emp.Salary) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("Scanned %d items: %+v\n", n, emp) }
The struct fields are passed as pointers to fmt.Fscanf
.
The %+v
verb prints the struct with field names.
Custom reader example
fmt.Fscanf
works with any type implementing io.Reader
.
This example uses a custom reader implementation.
package main import ( "fmt" "io" ) type ByteReader struct { data []byte pos int } func (r *ByteReader) Read(p []byte) (n int, err error) { if r.pos >= len(r.data) { return 0, io.EOF } n = copy(p, r.data[r.pos:]) r.pos += n return n, nil } func main() { data := []byte("3.14 42 hello") reader := &ByteReader{data: data} var pi float64 var num int var word string n, err := fmt.Fscanf(reader, "%f %d %s", &pi, &num, &word) if err != nil { fmt.Println("Error:", err) return } fmt.Printf("Scanned %d items: %.2f %d %s\n", n, pi, num, word) }
The custom ByteReader
implements the io.Reader
interface. fmt.Fscanf
works with it just like any other reader.
Source
This tutorial covered the fmt.Fscanf
function in Go with practical
examples of formatted input parsing from various sources.
Author
List all Golang tutorials.