ZetCode

Golang fmt.Sscan 函数

最后修改时间 2025 年 5 月 8 日

本教程解释了如何在 Go 中使用 fmt.Sscan 函数。我们将通过格式化输入的实际示例来涵盖字符串解析基础知识。

fmt.Sscan 函数扫描一个字符串并将连续的空格分隔值存储到参数中。它返回成功扫描的项目数和遇到的任何错误。

在 Go 中,fmt.Sscan 对于将简单的字符串数据解析到变量中非常有用。它是 fmt 包的一部分,该包处理格式化 I/O 操作。

基本的 fmt.Sscan 示例

fmt.Sscan 最简单的用法是从字符串解析空格分隔的值。此示例演示了基本的字符串扫描。
注意:输入字符串中的值必须用空格分隔。

basic_sscan.go
package main

import (
    "fmt"
)

func main() {
    var name string
    var age int
    
    input := "John 42"
    
    n, err := fmt.Sscan(input, &name, &age)
    if err != nil {
        fmt.Println("Error scanning:", err)
        return
    }
    
    fmt.Printf("Scanned %d values: %s is %d years old\n", n, name, age)
}

代码将输入字符串中的两个值扫描到变量中。该函数返回成功扫描的项目数和任何错误。

扫描多个值

fmt.Sscan 可以从字符串解析不同类型的多个值。此示例显示了扫描各种数据类型。

multiple_values.go
package main

import (
    "fmt"
)

func main() {
    var (
        name   string
        age    int
        height float64
        active bool
    )
    
    input := "Alice 25 1.68 true"
    
    n, err := fmt.Sscan(input, &name, &age, &height, &active)
    if err != nil {
        fmt.Println("Error scanning:", err)
        return
    }
    
    fmt.Printf("Scanned %d values:\n", n)
    fmt.Printf("Name: %s\nAge: %d\nHeight: %.2f\nActive: %t\n", 
        name, age, height, active)
}

该示例从单个字符串扫描字符串、整数、浮点数和布尔值。每个值都必须与变量中预期的类型匹配。

处理扫描错误

当输入与预期类型不匹配时,fmt.Sscan 会返回错误。此示例演示了错误处理。

error_handling.go
package main

import (
    "fmt"
)

func main() {
    var count int
    var price float64
    
    inputs := []string{
        "5 9.99",    // valid
        "five 9.99",  // invalid
        "5 nine",     // invalid
    }
    
    for _, input := range inputs {
        n, err := fmt.Sscan(input, &count, &price)
        if err != nil {
            fmt.Printf("Error scanning '%s': %v\n", input, err)
            continue
        }
        fmt.Printf("Scanned %d items from '%s': %d, %.2f\n", 
            n, input, count, price)
    }
}

代码尝试扫描不同的输入字符串。无效输入会产生错误,我们在程序中对其进行优雅处理。

扫描到结构体

我们可以使用 fmt.Sscan 从字符串填充结构体字段。此示例显示了结构化数据解析。

struct_scanning.go
package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
    City string
}

func main() {
    var p Person
    
    input := "Bob 35 NewYork"
    
    n, err := fmt.Sscan(input, &p.Name, &p.Age, &p.City)
    if err != nil {
        fmt.Println("Error scanning:", err)
        return
    }
    
    fmt.Printf("Scanned %d fields into struct:\n%+v\n", n, p)
}

该示例将值直接扫描到结构体的字段中。结构体必须具有导出的字段(大写名称)才能访问。

将 Sscan 与可变参数一起使用

我们可以使用 fmt.Sscan 的可变参数来创建灵活的扫描函数。此示例展示了一个可重用的扫描函数。

variadic_scanning.go
package main

import (
    "fmt"
)

func scanValues(input string, values ...interface{}) error {
    n, err := fmt.Sscan(input, values...)
    if err != nil {
        return err
    }
    if n != len(values) {
        return fmt.Errorf("expected %d values, got %d", len(values), n)
    }
    return nil
}

func main() {
    var id int
    var name string
    var score float64
    
    input := "101 Alice 95.5"
    
    err := scanValues(input, &id, &name, &score)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    
    fmt.Printf("ID: %d, Name: %s, Score: %.1f\n", id, name, score)
}

scanValues 函数接受任意数量的指针进行扫描。它提供了对扫描项目计数的额外验证。

使用自定义分隔符扫描

虽然 fmt.Sscan 默认使用空格,但我们可以预处理字符串以处理其他分隔符。此示例显示了逗号分隔的解析。

custom_delimiters.go
package main

import (
    "fmt"
    "strings"
)

func main() {
    var item string
    var quantity int
    var price float64
    
    input := "apple,5,1.99"
    
    // Replace commas with spaces
    normalized := strings.ReplaceAll(input, ",", " ")
    
    n, err := fmt.Sscan(normalized, &item, &quantity, &price)
    if err != nil {
        fmt.Println("Error scanning:", err)
        return
    }
    
    fmt.Printf("Scanned %d items: %d %s at $%.2f each\n", 
        n, quantity, item, price)
}

代码在扫描前将逗号转换为空格。此技术适用于简单情况,但对于复杂解析,请考虑使用 strings.Split

使用 Sscanf 进行高级扫描

为了更精确地控制解析,fmt.Sscanf 提供了格式化扫描。此示例比较了 Sscan 和 Sscanf。

advanced_scanning.go
package main

import (
    "fmt"
)

func main() {
    var a, b, c int
    
    input := "10-20-30"
    
    // Using Sscan (requires space separation)
    n1, err1 := fmt.Sscan(strings.ReplaceAll(input, "-", " "), &a, &b, &c)
    fmt.Printf("Sscan: %d,&v → %d %d %d\n", n1, err1, a, b, c)
    
    // Using Sscanf with format string
    n2, err2 := fmt.Sscanf(input, "%d-%d-%d", &a, &b, &c)
    fmt.Printf("Sscanf: %d,&v → %d %d %d\n", n2, err2, a, b, c)
}

fmt.Sscanf 提供了对格式说明符的更精确控制。根据您的解析需求,在 Sscan 和 Sscanf 之间进行选择。

来源

Go fmt 包文档

本教程通过字符串解析和格式化输入处理的实际示例,涵盖了 Go 中的 fmt.Sscan 函数。

作者

我叫 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教学编程方面拥有十多年的经验。

列出所有 Golang 教程