ZetCode

Golang fmt.Fscan function

last modified May 8, 2025

This tutorial explains how to use the fmt.Fscan function in Go. We'll cover input scanning basics with practical examples of reading data.

The fmt.Fscan function reads formatted input from an io.Reader. It scans text from the reader, storing successive space-separated values. Values are stored in the pointers passed as additional arguments.

In Go, fmt.Fscan is part of the fmt package's scanning functions. It's useful for reading structured data from files, strings, or network connections. The function returns the number of items successfully scanned.

Basic Fscan usage

The simplest use of fmt.Fscan reads values from a string reader. This example demonstrates basic scanning of different data types.
Note: Values must be passed as pointers to be modified.

basic_fscan.go
package main

import (
    "fmt"
    "strings"
)

func main() {
    input := "42 3.14 hello"
    reader := strings.NewReader(input)
    
    var i int
    var f float64
    var s string
    
    n, err := fmt.Fscan(reader, &i, &f, &s)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d items: %d, %f, %q\n", n, i, f, s)
}

The code reads an integer, float, and string from the input string. The function returns the count of successfully scanned items and any error.

Reading from standard input

fmt.Fscan can read directly from standard input using os.Stdin. This example shows interactive input scanning from the console.

stdin_fscan.go
package main

import (
    "fmt"
    "os"
)

func main() {
    var name string
    var age int
    
    fmt.Print("Enter your name and age: ")
    
    n, err := fmt.Fscan(os.Stdin, &name, &age)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d items\n", n)
    fmt.Printf("Hello %s, you are %d years old\n", name, age)
}

The program waits for user input from the terminal. Values are separated by whitespace. The function reads until it fills all provided variables.

Reading from a file

fmt.Fscan is commonly used to read structured data from files. This example demonstrates reading multiple records from a text file.

file_fscan.go
package main

import (
    "fmt"
    "os"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    file, err := os.Open("data.txt")
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close()
    
    var people []Person
    
    for {
        var p Person
        n, err := fmt.Fscan(file, &p.Name, &p.Age)
        
        if err != nil || n != 2 {
            break
        }
        
        people = append(people, p)
    }
    
    fmt.Println("People data:")
    for _, p := range people {
        fmt.Printf("%s: %d\n", p.Name, p.Age)
    }
}

The code reads name-age pairs from a file until EOF. Each line in the file should contain a name and age separated by whitespace.

Handling different data formats

fmt.Fscan can parse various data formats automatically. This example shows scanning different numeric formats and strings.

formats_fscan.go
package main

import (
    "fmt"
    "strings"
)

func main() {
    input := "0x1A 1.5e3 true Golang"
    reader := strings.NewReader(input)
    
    var hex int
    var sci float64
    var flag bool
    var lang string
    
    n, err := fmt.Fscan(reader, &hex, &sci, &flag, &lang)
    
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("Scanned %d items:\n", n)
    fmt.Printf("Hex: %d\n", hex)
    fmt.Printf("Scientific: %f\n", sci)
    fmt.Printf("Boolean: %t\n", flag)
    fmt.Printf("String: %q\n", lang)
}

The function automatically converts hexadecimal, scientific notation, and boolean values. It handles different base representations of numbers.

Reading multiple lines

fmt.Fscan can read across multiple lines in the input. This example demonstrates reading a multi-line input structure.

multiline_fscan.go
package main

import (
    "fmt"
    "strings"
)

func main() {
    input := `Product: Laptop
Price: 999.99
InStock: true`
    
    reader := strings.NewReader(input)
    
    var product string
    var price float64
    var inStock bool
    
    // Skip labels
    var label string
    
    fmt.Fscan(reader, &label, &product)
    fmt.Fscan(reader, &label, &price)
    fmt.Fscan(reader, &label, &inStock)
    
    fmt.Printf("%s: $%.2f (In stock: %t)\n", 
        product, price, inStock)
}

The code reads labeled data spread across multiple lines. It skips the labels while storing the actual values in variables.

Error handling in Fscan

Proper error handling is crucial when using fmt.Fscan. This example shows comprehensive error checking for input scanning.

error_fscan.go
package main

import (
    "fmt"
    "strings"
)

func main() {
    tests := []string{
        "100 200",          // valid
        "100 abc",         // invalid
        "100 200 300",     // extra
        "100",             // insufficient
    }
    
    for _, input := range tests {
        reader := strings.NewReader(input)
        var a, b int
        
        n, err := fmt.Fscan(reader, &a, &b)
        
        fmt.Printf("Input: %q\n", input)
        fmt.Printf("Scanned %d items\n", n)
        
        if err != nil {
            fmt.Println("Error:", err)
        } else {
            fmt.Printf("Values: %d, %d\n", a, b)
        }
        
        fmt.Println("-----")
    }
}

The code tests various input scenarios and shows how errors are reported. Different types of input problems produce different error conditions.

Advanced Fscan usage

fmt.Fscan can be combined with custom io.Reader implementations. This example shows scanning from a custom data source.

custom_reader.go
package main

import (
    "fmt"
    "io"
)

type Rot13Reader struct {
    r io.Reader
}

func (r Rot13Reader) Read(p []byte) (n int, err error) {
    n, err = r.r.Read(p)
    for i := 0; i < n; i++ {
        switch {
        case p[i] >= 'A' && p[i] <= 'Z':
            p[i] = (p[i]-'A'+13)%26 + 'A'
        case p[i] >= 'a' && p[i] <= 'z':
            p[i] = (p[i]-'a'+13)%26 + 'a'
        }
    }
    return
}

func main() {
    input := "Uryyb Jbeyq"
    rot := Rot13Reader{strings.NewReader(input)}
    
    var hello, world string
    fmt.Fscan(&rot, &hello, &world)
    
    fmt.Println(hello, world) // Output: Hello World
}

The custom Rot13Reader decrypts text before scanning. This demonstrates how fmt.Fscan can work with any io.Reader implementation.

Source

Go package documentation

This tutorial covered the fmt.Fscan function in Go with practical examples of reading formatted input from various sources.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Golang tutorials.