1. fmt包中的标准输入用法
Go 语言的 fmt
包提供了一系列用于格式化I/O操作的函数,其中包括从标准输入读取数据的功能。这些功能主要通过 fmt.Scan
、fmt.Scanf
和 fmt.Scanln
函数实现。下面将详细介绍这三个函数的用途和用法。
fmt.Scan
fmt.Scan
从标准输入读取数据,直到遇到空格或换行符为止。它将读取的数据赋值给提供的参数。如果函数调用时没有提供任何参数,fmt.Scan
将不会读取任何数据。
var a int
var b string
fmt.Scan(&a, &b)
在这个例子中,fmt.Scan
会从标准输入中读取两个值:第一个值被解析为整数并赋给变量 a
,第二个值被读取为字符串直到遇到空格或换行符,并赋给变量 b
。
fmt.Scanf
fmt.Scanf
根据指定的格式字符串从标准输入读取数据,并根据格式字符串将读取的数据分配到提供的参数中。格式字符串指定了输入数据应该满足的格式。
var a int
var b string
fmt.Scanf("%d %s", &a, &b)
在这个例子中,fmt.Scanf
期望从标准输入中读取一个整数和一个字符串,两者之间由空格分隔。读取的整数赋给变量 a
,字符串赋给变量 b
。
fmt.Scanln
fmt.Scanln
类似于 fmt.Scan
,但它在遇到换行符时停止读取。fmt.Scanln
会读取一整行的输入(直到换行符),并将这一行的数据根据空格分隔,分别赋值给提供的参数。
var a int
var b string
fmt.Scanln(&a, &b)
在这个例子中,fmt.Scanln
从标准输入中读取一行数据,尝试将这行数据的第一个部分解析为整数赋给 a
,将第二部分赋给 b
。如果这行数据中包含更多的数据,它们将被忽略。
注意事项
- 当使用这些函数时,需要提供变量的地址(使用
&
操作符),因为函数需要在给定的内存地址中直接修改变量的值。 - 这些函数在成功读取数据时会返回读取的项目数量和遇到的任何错误。特别是,如果读取的数据数量少于提供的参数数量,函数将返回一个错误。
- 使用
fmt.Scanf
时,格式字符串需要准确匹配输入的格式,包括空格和换行符,这可能会使得它在处理不规则输入时变得复杂。
这些基于 fmt
包的标准输入函数非常适合用于简单的命令行程序或初学者练习,但在需要处理更复杂的输入或大量数据时,可能需要使用更专业的输入方法,如 bufio.Scanner
。
2.bufio包中的标准输入用法
Go 语言的 bufio
包提供了缓冲I/O操作的支持,它包装了 io.Reader
和 io.Writer
接口,提供了数据的缓冲功能,可以提高读写操作的效率,当需要大量读写操作的时候bufio的效率十分高效。在处理标准输入(os.Stdin
)时,bufio
包中的 Scanner
类型是一个非常有用的工具,尤其是用于读取输入中的行或单词。
bufio.Scanner
bufio.Scanner
是用于读取数据的一个便捷接口,它可以按行或按指定的分隔符进行读取。默认情况下,Scanner
使用换行符作为数据的分隔符,这使得按行读取文本数据变得非常简单。
创建 Scanner
首先,你需要使用 bufio.NewScanner
函数创建一个 Scanner
对象,并将 os.Stdin
作为输入源传递给它:
scanner := bufio.NewScanner(os.Stdin)
读取数据
然后,你可以使用 Scan
方法在输入源上进行扫描。Scan
方法在每次调用时都会读取下一个项目(默认为下一行),直到没有更多的数据可以读取。如果 Scan
返回 true
,则表示成功读取了数据;如果返回 false
,则表示没有更多的数据或遇到了错误。
for scanner.Scan() {
line := scanner.Text() // 获取当前行的文本
fmt.Println("输入的行:", line)
}
错误处理
在循环结束后,你应该检查 Scan
循环是否因为遇到错误而终止。可以通过 Err
方法来检查是否有任何错误发生:
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "读取错误:", err)
}
自定义分隔符
如果你想按照不同的规则来分割输入(例如,按单词或特定字符分割),bufio.Scanner
提供了 Split
方法来设置自定义的分隔函数。bufio
包预定义了一些分隔函数(如按字节、行、单词分割),也可以定义自己的分隔函数。
scanner.Split(bufio.ScanWords) // 设置分隔函数为按单词分割
示例:按行读取
下面是一个使用 bufio.Scanner
按行读取标准输入的完整示例:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("请输入一些文本,按行读取:")
for scanner.Scan() {
line := scanner.Text()
fmt.Println("输入的行:", line)
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "读取错误:", err)
}
}
这个示例程序会不断读取用户输入的每一行文本,直到输入结束(在命令行中通常通过 Ctrl+D(Linux/macOS)或 Ctrl+Z(Windows)来发送结束信号)。
bufio
包中的 Scanner
类型是处理标准输入文本数据的强大工具,尤其是当你需要按行或按特定模式读取数据时。它既灵活又易于使用,是许多 Go 程序的首选工具。
3. 区别
fmt
包和 bufio
包提供的标准输入方法都是 Go 语言用于读取用户输入的常用方式,但它们在设计理念、使用场景和功能特性上存在一些差异。
- 快速原型和简单输入:如果你只是在做一些快速原型制作或者需要处理一些非常简单的输入,
fmt
包可能是更直接、更简单的选择。 - 复杂的输入处理和性能要求:对于需要高效处理大量数据、按特定模式读取数据或者需要更细粒度控制输入处理的场景,
bufio
包会是更好的选择。