Golang fmt.Fscan 函数
最后修改时间 2025 年 5 月 8 日
本教程解释了如何在 Go 中使用 fmt.Fscan
函数。我们将通过实际的读取数据示例涵盖输入扫描基础知识。
fmt.Fscan
函数从 io.Reader 读取格式化输入。它从读取器扫描文本,存储连续的以空格分隔的值。值存储在作为附加参数传递的指针中。
在 Go 中,fmt.Fscan
是 fmt 包扫描函数的一部分。它对于从文件、字符串或网络连接读取结构化数据非常有用。该函数返回成功扫描的项目数。
Fscan 的基本用法
fmt.Fscan
最简单的用法是从字符串读取器读取值。此示例演示了对不同数据类型的基本扫描。
注意:必须将值作为指针传递才能进行修改。
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) }
代码从输入字符串中读取一个整数、一个浮点数和一个字符串。该函数返回成功扫描的项数以及任何错误。
从标准输入读取
fmt.Fscan
可以直接使用 os.Stdin 从标准输入读取。此示例显示了从控制台进行交互式输入扫描。
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) }
程序等待来自终端的用户输入。值由空格分隔。该函数一直读取,直到填满所有提供的变量。
从文件读取
fmt.Fscan
通常用于从文件读取结构化数据。此示例演示了从文本文件读取多个记录。
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) } }
代码从文件中读取姓名-年龄对,直到文件结束 (EOF)。文件中的每一行都应该包含一个姓名和年龄,它们之间用空格分隔。
处理不同的数据格式
fmt.Fscan
可以自动解析各种数据格式。此示例显示了扫描不同的数字格式和字符串。
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) }
该函数自动转换十六进制、科学计数法和布尔值。它处理数字的不同基数表示。
读取多行
fmt.Fscan
可以跨输入的多行进行读取。此示例演示了读取多行输入结构。
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) }
代码读取分布在多行中的带标签的数据。它会跳过标签,同时将实际值存储在变量中。
Fscan 中的错误处理
在使用 fmt.Fscan
时,正确的错误处理至关重要。此示例展示了输入扫描的全面错误检查。
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("-----") } }
代码测试了各种输入场景,并展示了错误是如何报告的。不同类型的输入问题会产生不同的错误条件。
Fscan 的高级用法
fmt.Fscan
可以与自定义的 io.Reader 实现结合使用。此示例展示了从自定义数据源进行扫描。
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 }
自定义的 Rot13Reader 在扫描前解密文本。这表明 fmt.Fscan
可以与任何 io.Reader 实现配合使用。
来源
本教程通过从各种源读取格式化输入的实际示例,涵盖了 Go 中的 fmt.Fscan
函数。