如何从Go的标准输入读取:从新手到专家
您是否曾想过如何让您的Go程序“倾听”用户?如何编写一个从控制台接受命令的实用程序,或一个交互式CLI工具?如果是这样,那么您来对地方了。今天我们将详细解析在Go中从标准输入(stdin)读取——尽可能详细。
这个话题在Stack Overflow上非常热门。问题“How can I read from standard input in the console?” 获得了数千次浏览。这并非偶然:标准输入是基础,任何严肃的Go项目都离不开它。我们将针对中文受众改编这个问题,并将其变成一个完整的教程。
在本文中,您将了解到:
- 什么是
os.Stdin以及如何使用它 - 如何使用
bufio.Scanner进行逐行读取 - 为什么
fmt.Scan是一把双刃剑 - 如何从stdin读取整个文件
- 错误处理和性能优化的秘诀
我们开始吧!
什么是stdin,为什么在Go中需要它?
标准输入(stdin)是您的程序从控制台或其他进程接收的数据流。在Go中,它由类型为*os.File的变量os.Stdin表示。这是数据进入您程序的通道。
为什么需要它?想象一下:
- 您正在编写一个CLI实用程序,用于处理用户输入
- 您正在创建一个日志解析器,通过管道读取数据(
cat log.txt | myapp) - 您需要实现带有提示的交互式输入
作为一门系统编程语言,Go提供了优雅的工具来处理stdin。让我们逐一分析它们。
方法1:bufio.Scanner —— 逐行读取之王
最流行且推荐的在Go中从stdin读取的方法是使用bufio.Scanner。它简单、高效,能解决90%的问题。
经典示例如下:
package main
import ( "bufio" "fmt" "os")
func main() { scanner := bufio.NewScanner(os.Stdin) fmt.Println("请输入文本(按Ctrl+D结束):") for scanner.Scan() { line := scanner.Text() fmt.Println("您输入了:", line) } if err := scanner.Err(); err != nil { fmt.Fprintln(os.Stderr, "读取错误:", err) }}它是如何工作的?
bufio.NewScanner(os.Stdin)— 创建一个从标准输入读取的扫描器scanner.Scan()— 只要有数据就返回true(默认直到换行符)scanner.Text()— 返回当前行,不含字符- 遇到
EOF时循环终止(Linux/Mac下按Ctrl+D,Windows下按Ctrl+Z)
这段代码是任何Go控制台输入的基础。它非常适合管道和交互式输入。
自定义Scanner
默认情况下,Scanner按行分割输入。但您可以更改此设置:
// 按单词读取scanner.Split(bufio.ScanWords)
// 按字节读取scanner.Split(bufio.ScanBytes)
// 按字符(符文)读取scanner.Split(bufio.ScanRunes)您还可以设置自己的分割器——例如,用于CSV或自定义分隔符。但这已是另一篇文章的主题了。
方法2:fmt.Scan —— 快速而粗糙
如果您需要输入一个值——数字、字符串或多个变量——fmt.Scan可以派上用场。它就像C语言中的scanf,只不过