ZetCode

Golang fmt.Sscanln 函数

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

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

fmt.Sscanln 函数从字符串中扫描以空格分隔的值。它在换行符处停止扫描,并要求输入以换行符或 EOF 结尾。它返回成功扫描的项目数。

在 Go 中,fmt.Sscanln 类似于 fmt.Scanln,但它从字符串而不是标准输入读取。它对于将结构化字符串数据解析到变量中很有用。

基本字符串扫描示例

fmt.Sscanln 最简单的用法是从字符串解析基本值。此示例演示了扫描整数和字符串。
注意:输入字符串必须与预期格式完全匹配。

basic_scan.go
package main

import (
    "fmt"
)

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

该函数从输入字符串扫描两个值。它返回成功扫描的项目数以及扫描过程中发生的任何错误。

扫描多个值

fmt.Sscanln 可以一次解析多种不同类型的值。此示例展示了从字符串扫描混合数据类型。

multiple_values.go
package main

import (
    "fmt"
)

func main() {
    var product string
    var price float64
    var inStock bool
    
    input := "Laptop 1299.99 true\n"
    
    n, err := fmt.Sscanln(input, &product, &price, &inStock)
    if err != nil {
        fmt.Println("Error scanning:", err)
        return
    }
    
    fmt.Printf("Scanned %d items: %s costs $%.2f (in stock: %t)\n", 
        n, product, price, inStock)
}

该示例从输入中扫描字符串、浮点数和布尔值。该函数在可能的情况下会自动将值转换为目标变量类型。

处理扫描错误

扫描不可预测的输入时,错误处理很重要。此示例演示了使用 fmt.Sscanln 进行的正确错误处理。

error_handling.go
package main

import (
    "fmt"
)

func main() {
    var x, y int
    
    tests := []string{
        "10 20\n",
        "10 abc\n",
        "10\n",
    }
    
    for _, input := range tests {
        n, err := fmt.Sscanln(input, &x, &y)
        if err != nil {
            fmt.Printf("Input: %q Error: %v (scanned %d items)\n", 
                input, err, n)
            continue
        }
        fmt.Printf("Scanned successfully: x=%d y=%d\n", x, y)
    }
}

该代码测试了不同的输入场景并适当地处理了错误。请注意,在发生错误时,它如何报告部分扫描结果。

使用指针进行扫描

fmt.Sscanln 需要指向变量的指针来存储扫描的值。此示例显示了正确的指针用法和要避免的常见错误。

pointer_usage.go
package main

import (
    "fmt"
)

func main() {
    var a int
    var b float64
    var c string
    
    // Correct way: passing pointers
    input1 := "42 3.14 hello\n"
    n1, err1 := fmt.Sscanln(input1, &a, &b, &c)
    if err1 != nil {
        fmt.Println("Error:", err1)
    } else {
        fmt.Printf("Scanned %d values: %d, %.2f, %q\n", n1, a, b, c)
    }
    
    // Incorrect way: passing values (will not compile)
    // n2, err2 := fmt.Sscanln(input1, a, b, c)
}

该示例对比了正确的指针用法和错误的值传递。请记住,所有目标变量都必须作为指针传递。

扫描到结构体字段

我们可以直接使用指针扫描到结构体字段中。此示例演示了使用 fmt.Sscanln 进行的结构化数据解析。

struct_scanning.go
package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
    City string
}

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

该代码直接将值扫描到结构体的字段中。这种模式对于将字符串数据转换为 Go 的结构化类型非常有用。

自定义类型扫描

fmt.Sscanln 可与实现 Scanner 接口的自定义类型一起使用。此示例展示了如何为自定义类型启用扫描。

custom_type.go
package main

import (
    "fmt"
    "strings"
)

type RGB struct {
    R, G, B int
}

func (c *RGB) Scan(f fmt.ScanState, verb rune) error {
    _, err := fmt.Fscanf(f, "%d,%d,%d", &c.R, &c.G, &c.B)
    return err
}

func main() {
    var color RGB
    input := "255,128,0\n"
    
    _, err := fmt.Sscanln(input, &color)
    if err != nil {
        fmt.Println("Error scanning color:", err)
        return
    }
    
    fmt.Printf("Scanned color: R=%d G=%d B=%d\n", color.R, color.G, color.B)
}

RGB 类型实现了 Scanner 接口。这使得 fmt.Sscanln 能够解析自定义格式的数据。

扫描可变长度的输入

我们可以使用扫描来处理具有不同数量值的输入。此示例展示了使用 fmt.Sscanln 进行的灵活输入解析。

varying_input.go
package main

import (
    "fmt"
)

func main() {
    inputs := []string{
        "100\n",
        "100 200\n",
        "100 200 300\n",
    }
    
    for _, input := range inputs {
        var a, b, c int
        n, err := fmt.Sscanln(input, &a, &b, &c)
        if err != nil && n < 3 {
            fmt.Printf("Input: %q Scanned %d values: a=%d b=%d c=%d\n",
                input, n, a, b, c)
            continue
        }
        fmt.Printf("Fully scanned: a=%d b=%d c=%d\n", a, b, c)
    }
}

该代码处理具有不同数量值的输入。当输入不包含所有预期值时,它会报告部分扫描结果。

来源

Go 包文档

本教程通过字符串解析和扫描技术的实际示例,涵盖了 Go 中的 fmt.Sscanln 函数。

作者

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

列出所有 Golang 教程