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.