【Go】fmt与bufio的标准输入

1. fmt包中的标准输入用法

Go 语言的 fmt 包提供了一系列用于格式化I/O操作的函数,其中包括从标准输入读取数据的功能。这些功能主要通过 fmt.Scanfmt.Scanffmt.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.Readerio.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 包会是更好的选择。
  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值