0

0

Go语言教程:使用bufio.Scanner从标准输入读取行并按条件终止

花韻仙語

花韻仙語

发布时间:2025-09-27 10:23:11

|

924人浏览过

|

来源于php中文网

原创

Go语言教程:使用bufio.Scanner从标准输入读取行并按条件终止

本教程详细介绍了在Go语言中如何高效地从标准输入逐行读取数据,并实现当遇到特定字符(如单个点)时终止输入流。我们将重点讲解Go 1.1版本后引入的bufio.Scanner的用法,它能简化输入处理,并自动处理行尾换行符,从而实现简洁而健壮的解决方案。

1. 理解需求:从标准输入读取直到特定标记

在许多交互式程序中,我们经常需要从用户的标准输入(stdin)读取多行数据,直到用户输入一个特定的“终止符”或“哨兵值”。例如,程序可能需要读取一系列文本行,直到用户输入一个单独的句点(.)来表示输入结束。

早期的Go版本或不熟悉bufio包特性的开发者可能会尝试使用bufio.NewReader配合ReadString('\n')来实现。然而,这种方法存在一个常见的陷阱:ReadString('\n')会读取包括换行符在内的整行内容。这意味着,如果用户输入“.”,实际读取到的字符串会是“.\n”,这与我们期望的“.”不匹配,导致判断条件失效。

2. Go语言的现代解决方案:bufio.Scanner

自Go 1.1版本起,bufio包引入了Scanner类型,它提供了一种更简洁、更高效且更符合Go语言习惯的方式来处理流式输入,特别是按行读取。Scanner会自动处理缓冲区和换行符,极大地简化了代码。

以下是使用bufio.Scanner实现从标准输入读取行直到遇到单个句点(.)的示例代码:

package main

import (
    "bufio" // 导入bufio包,用于Scanner
    "fmt"   // 导入fmt包,用于打印输出
    "os"    // 导入os包,用于访问标准输入
)

func main() {
    // 1. 创建一个新的Scanner,它将从os.Stdin(标准输入)读取数据
    scanner := bufio.NewScanner(os.Stdin)

    fmt.Println("请输入文本行,输入 '.' (不含引号) 终止:")

    // 2. 循环读取每一行
    // scanner.Scan() 会读取下一行,如果成功读取则返回 true,否则返回 false(例如,到达文件末尾或发生错误)
    for scanner.Scan() {
        // 3. 使用 scanner.Text() 获取当前行的文本内容
        // scanner.Text() 会自动移除行尾的换行符(\n或\r\n),这是其主要优势之一。
        line := scanner.Text()

        // 4. 检查当前行是否为终止符
        if line == "." {
            // 如果是终止符,则跳出循环
            break
        }

        // 5. 对读取到的行进行处理(这里只是简单打印出来)
        fmt.Println("您输入了:", line)
    }

    // 6. 循环结束后,检查是否有错误发生
    // 在循环结束后,可以通过 scanner.Err() 检查在扫描过程中是否发生了非EOF错误。
    if err := scanner.Err(); err != nil {
        fmt.Fprintf(os.Stderr, "读取标准输入时发生错误: %v\n", err)
    }

    fmt.Println("输入结束。")
}

3. 代码解析与关键点

  1. bufio.NewScanner(os.Stdin):

    立即学习go语言免费学习笔记(深入)”;

    • 这是创建Scanner实例的第一步。它接受一个io.Reader接口作为参数,os.Stdin(标准输入)正好实现了这个接口。
    • Scanner内部会维护一个缓冲区,以提高读取效率。
  2. for scanner.Scan():

    Meituan CatPaw
    Meituan CatPaw

    美团推出的智能AI编程Agent

    下载
    • 这是一个典型的Go语言循环结构,用于迭代处理输入流。
    • scanner.Scan()方法是核心:
      • 它会尝试从输入源读取下一“token”(默认是下一行,由SplitFunc决定)。
      • 如果成功读取到token,它会返回true,并且该token(行)的数据会存储在Scanner的内部缓冲区中。
      • 如果遇到文件结束符(EOF)或发生错误,它会返回false。
    • 这个循环会持续执行,直到Scan()返回false。
  3. line := scanner.Text():

    • 当scanner.Scan()返回true后,scanner.Text()方法用于获取当前成功读取的token(即一行)的字符串表示。
    • 关键特性:scanner.Text()会自动去除行尾的换行符(\n或\r\n)。这意味着,如果用户输入“.”,line变量的值将精确地是字符串“.”,而不是“.\n”,这使得条件判断非常直观和准确。
  4. if line == "." { break }:

    • 这是实现条件终止的关键逻辑。当scanner.Text()返回的字符串与我们预设的终止符(这里是单个句点)完全匹配时,break语句会立即跳出for循环,从而结束输入读取过程。
  5. 错误处理 if err := scanner.Err(); err != nil:

    • 在for scanner.Scan()循环结束后,强烈建议检查scanner.Err()。
    • 如果Scan()因非EOF错误而返回false,scanner.Err()将返回相应的错误信息。这对于构建健壮的应用程序至关重要。

4. 注意事项与最佳实践

  • bufio.Scanner的默认行为: 默认情况下,Scanner使用bufio.ScanLines作为其分割函数(SplitFunc),这意味着它会按行读取。你可以通过scanner.Split()方法来改变分割行为,例如按单词、按字节等。
  • 性能: bufio.Scanner内部使用缓冲区,这使得它在处理大量输入时非常高效。
  • 简洁性: 相较于手动处理ReadString和去除换行符,Scanner的API更加简洁直观,减少了出错的可能性。

总结

bufio.Scanner是Go语言中处理流式输入,特别是逐行读取标准输入或文件内容的推荐方式。它通过自动管理缓冲区和智能处理行尾换行符,极大地简化了输入处理逻辑,使得代码更加清晰、健壮。在需要从输入流中读取数据直到遇到特定终止符的场景下,bufio.Scanner提供了一个优雅且高效的解决方案。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

771

2023.08.22

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6113

2023.09.14

登录token无效怎么办
登录token无效怎么办

登录token无效的解决办法有检查Token是否过期、检查Token是否正确、检查Token是否被篡改、检查Token是否与用户匹配、清除缓存或Cookie、检查网络连接和服务器状态、重新登录或请求新的Token、联系技术支持或开发人员等。本专题为大家提供token相关的文章、下载、课程内容,供大家免费下载体验。

816

2023.09.14

token怎么获取
token怎么获取

获取token值的方法:1、小程序调用“wx.login()”获取 临时登录凭证code,并回传到开发者服务器;2、开发者服务器以code换取,用户唯一标识openid和会话密钥“session_key”。想了解更详细的内容,可以阅读本专题下面的文章。

1064

2023.12.21

token什么意思
token什么意思

token是一种用于表示用户权限、记录交易信息、支付虚拟货币的数字货币。可以用来在特定的网络上进行交易,用来购买或出售特定的虚拟货币,也可以用来支付特定的服务费用。想了解更多token什么意思的相关内容可以访问本专题下面的文章。

1306

2024.03.01

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

118

2025.10.15

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

256

2025.10.24

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

298

2023.08.03

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

58

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4.2万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号