Golang fmt.Sscan 函数
最后修改时间 2025 年 5 月 8 日
本教程解释了如何在 Go 中使用 fmt.Sscan 函数。我们将通过格式化输入的实际示例来涵盖字符串解析基础知识。
fmt.Sscan 函数扫描一个字符串并将连续的空格分隔值存储到参数中。它返回成功扫描的项目数和遇到的任何错误。
在 Go 中,fmt.Sscan 对于将简单的字符串数据解析到变量中非常有用。它是 fmt 包的一部分,该包处理格式化 I/O 操作。
基本的 fmt.Sscan 示例
fmt.Sscan 最简单的用法是从字符串解析空格分隔的值。此示例演示了基本的字符串扫描。
注意:输入字符串中的值必须用空格分隔。
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 可以从字符串解析不同类型的多个值。此示例显示了扫描各种数据类型。
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 会返回错误。此示例演示了错误处理。
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 从字符串填充结构体字段。此示例显示了结构化数据解析。
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 的可变参数来创建灵活的扫描函数。此示例展示了一个可重用的扫描函数。
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 默认使用空格,但我们可以预处理字符串以处理其他分隔符。此示例显示了逗号分隔的解析。
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。
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.Sscan 函数。