Golang fmt.Fscanln 函数
最后修改时间 2025 年 5 月 8 日
本教程将解释如何在 Go 中使用 fmt.Fscanln 函数。我们将通过实际示例介绍输入扫描基础知识,包括从各种来源读取格式化输入。
fmt.Fscanln 函数从 io.Reader 读取,并将空格分隔的值扫描到连续的参数中。它在换行符处停止扫描,并且在最后一个项目之后,必须有一个换行符或 EOF。
在 Go 中,fmt.Fscanln 类似于 fmt.Scanln,但它适用于任何 io.Reader。它对于从文件、网络连接或自定义读取器读取结构化输入非常有用。
Fscanln 的基本用法
fmt.Fscanln 最简单的用法是从字符串读取器读取值。此示例演示了基本的输入扫描。
注意:值必须用空格分隔,并以换行符结尾。
package main
import (
"fmt"
"strings"
)
func main() {
input := "John 25 true\n"
reader := strings.NewReader(input)
var name string
var age int
var active bool
n, err := fmt.Fscanln(reader, &name, &age, &active)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Read %d values: %s, %d, %t\n", n, name, age, active)
}
代码从字符串中读取三种不同的类型。该函数返回成功扫描的项目数以及遇到的任何错误。
从标准输入读取
fmt.Fscanln 可以直接使用 os.Stdin 从标准输入读取。此示例展示了交互式输入扫描。
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("Enter your name and age (separated by space):")
var name string
var age int
n, err := fmt.Fscanln(os.Stdin, &name, &age)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Hello %s! You are %d years old.\n", name, age)
fmt.Printf("Successfully read %d values.\n", n)
}
程序等待用户输入并读取两个值。Fscanln 要成功完成,输入后的换行符是必需的。
从文件读取
fmt.Fscanln 通常用于从文件中读取结构化数据。此示例演示了文件输入扫描。
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("data.txt")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
var product string
var price float64
var quantity int
_, err = fmt.Fscanln(file, &product, &price, &quantity)
if err != nil {
fmt.Println("Error reading file:", err)
return
}
fmt.Printf("Product: %s\nPrice: $%.2f\nQuantity: %d\n",
product, price, quantity)
}
代码从包含产品数据的文件中读取一行。请记住处理文件打开错误并在完成后关闭文件。
处理多行
要读取多行,请在循环中使用 fmt.Fscanln。此示例展示了如何逐行处理结构化数据。
package main
import (
"bufio"
"fmt"
"strings"
)
func main() {
data := `Alice 25
Bob 30
Charlie 35`
scanner := bufio.NewScanner(strings.NewReader(data))
for scanner.Scan() {
line := scanner.Text()
reader := strings.NewReader(line)
var name string
var age int
_, err := fmt.Fscanln(reader, &name, &age)
if err != nil {
fmt.Println("Error:", err)
continue
}
fmt.Printf("%s is %d years old\n", name, age)
}
}
代码将 bufio.Scanner 与行读取结合使用,并将 Fscanln 与行解析结合使用。这种模式对于结构化文本处理非常高效。
读取不同的数据类型
fmt.Fscanln 可以自动处理各种 Go 类型。此示例演示了从输入中读取混合数据类型。
package main
import (
"fmt"
"strings"
)
func main() {
input := "Go 1.21 true 42\n"
reader := strings.NewReader(input)
var lang string
var version float64
var compiled bool
var year int
n, err := fmt.Fscanln(reader, &lang, &version, &compiled, &year)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Read %d values:\n", n)
fmt.Println("Language:", lang)
fmt.Println("Version:", version)
fmt.Println("Compiled:", compiled)
fmt.Println("Year:", year)
}
该函数会自动将输入字符串转换为目标变量类型。如果输入与预期类型不匹配,则会返回转换错误。
错误处理
在使用 fmt.Fscanln 时,正确处理错误至关重要。此示例显示了全面的错误检查。
package main
import (
"fmt"
"strings"
)
func main() {
testCases := []string{
"100 200\n",
"100\n",
"100 abc\n",
"100 200 300\n",
}
for _, input := range testCases {
reader := strings.NewReader(input)
var a, b int
n, err := fmt.Fscanln(reader, &a, &b)
fmt.Printf("Input: %q\n", input)
if err != nil {
fmt.Println(" Error:", err)
} else {
fmt.Printf(" Read %d values: %d, %d\n", n, a, b)
}
}
}
代码测试了各种输入场景,并展示了 Fscanln 在不同输入下的行为。始终检查返回计数和错误。
读取到切片中
虽然 fmt.Fscanln 需要固定参数,但我们可以通过一些额外的代码读取到切片中。此示例演示了该技术。
package main
import (
"fmt"
"strings"
)
func main() {
input := "5 10 15 20 25\n"
reader := strings.NewReader(input)
var nums []int
for {
var num int
n, err := fmt.Fscanln(reader, &num)
if n == 0 || err != nil {
break
}
nums = append(nums, num)
}
fmt.Println("Read numbers:", nums)
fmt.Println("Sum:", sum(nums))
}
func sum(nums []int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
代码读取数字,直到遇到错误。当您无法预测值的数量时,这种模式对于读取可变长度的输入非常有用。
来源
本教程通过从各种来源读取格式化输入的实际示例,涵盖了 Go 中的 fmt.Fscanln 函数。