0

0

深入理解Go语言标准输入:bufio、fmt.Scanln与fmt.Scanf

碧海醫心

碧海醫心

发布时间:2025-11-17 13:04:00

|

325人浏览过

|

来源于php中文网

原创

深入理解Go语言标准输入:bufio、fmt.Scanln与fmt.Scanf

本文详细探讨了go语言中从控制台读取标准输入的多种方法,包括使用`bufio.newreader`进行逐行读取,以及`fmt`包中的`scanln`和`scanf`函数。文章重点阐述了这些函数的正确用法,特别是`fmt.scanln`和`fmt.scanf`需要传入变量的指针,并区分了从标准输入读取与从内存字符串解析的不同场景,旨在帮助开发者高效准确地处理用户输入。

在Go语言开发中,与用户进行交互通常需要从控制台读取标准输入。Go提供了多种灵活的方式来实现这一功能,主要包括使用bufio包进行缓冲读取,以及fmt包提供的便捷函数。理解这些方法的异同和正确用法对于编写健壮的交互式程序至关重要。

使用 bufio.NewReader 逐行读取

bufio包提供了缓冲I/O操作,对于需要逐行读取或处理大量输入的场景非常适用。通过bufio.NewReader创建一个读取器,可以从os.Stdin(标准输入)中读取数据。

核心方法:

  • bufio.NewReader(os.Stdin): 创建一个新的Reader,关联到标准输入流。
  • reader.ReadString('\n'): 从输入流中读取直到遇到指定的分隔符(此处为换行符\n),并返回读取到的字符串(包含分隔符)和可能发生的错误。

示例代码:

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

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings" // 用于去除可能的换行符
)

func main() {
    reader := bufio.NewReader(os.Stdin)
    fmt.Print("请输入您的姓名: ")
    // ReadString会读取直到遇到换行符,并包含换行符
    name, err := reader.ReadString('\n')
    if err != nil {
        fmt.Println("读取输入时发生错误:", err)
        return
    }
    // 通常需要去除字符串末尾的换行符
    name = strings.TrimSpace(name) // TrimSpace可以去除字符串两端的空白字符,包括\n

    fmt.Printf("您好, %s!\n", name)
}

注意事项:ReadString返回的字符串会包含分隔符(例如\n)。在实际应用中,通常需要使用strings.TrimSpace()或strings.TrimSuffix(name, "\n")等函数去除这些额外的字符,以获得纯净的用户输入。同时,始终检查ReadString返回的错误,以确保输入操作成功。

使用 fmt.Scanln 读取整行输入

fmt.Scanln函数是fmt包中一个方便的函数,用于从标准输入中读取数据,直到遇到换行符。它会扫描并解析一行输入,将其中的值赋给提供的变量。

关键点:

Ideogram
Ideogram

Ideogram是一个全新的文本转图像AI绘画生成平台,擅长于生成带有文本的图像,如LOGO上的字母、数字等。

下载
  • 需要传入变量的指针: fmt.Scanln需要直接修改变量的值,因此必须传入变量的内存地址(即指针),而不是变量的副本。这是Go语言中函数修改外部变量的常见模式。
  • 读取到换行符后停止。

示例代码:

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

package main

import (
    "fmt"
)

func main() {
    var age int
    fmt.Print("请输入您的年龄: ")
    // 必须传入age变量的指针,即&age
    _, err := fmt.Scanln(&age)
    if err != nil {
        fmt.Println("读取年龄时发生错误:", err)
        return
    }
    fmt.Printf("您的年龄是: %d岁\n", age)

    var city string
    fmt.Print("请输入您所在的城市: ")
    // 对于字符串类型同样需要传入指针
    _, err = fmt.Scanln(&city)
    if err != nil {
        fmt.Println("读取城市时发生错误:", err)
        return
    }
    fmt.Printf("您居住在: %s\n", city)
}

错误用法: 如果尝试使用fmt.Scanln(city)而不是fmt.Scanln(&city),程序将无法将输入的值赋给city变量,因为函数接收到的是city的副本,对副本的修改不会影响原始变量。

使用 fmt.Scanf 格式化读取输入

fmt.Scanf函数允许您根据指定的格式字符串从标准输入中读取和解析数据,类似于C语言的scanf。它提供了更精细的控制,可以匹配不同类型的数据。

关键点:

  • 格式字符串: 第一个参数是格式字符串,例如"%s"用于字符串,"%d"用于整数,"%f"用于浮点数。
  • 需要传入变量的指针: 与fmt.Scanln一样,fmt.Scanf也需要传入变量的指针。
  • fmt.Scanf会根据格式字符串读取,并不会自动读取到行尾,可能会留下剩余输入在缓冲区。

示例代码:

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

package main

import (
    "fmt"
)

func main() {
    var firstName, lastName string
    fmt.Print("请输入您的姓和名(例如:张 三): ")
    // 使用%s读取两个字符串。注意这里的\n是为了匹配并消耗掉输入行末的换行符
    _, err := fmt.Scanf("%s %s\n", &firstName, &lastName) 
    if err != nil {
        fmt.Println("读取姓名时发生错误:", err)
        return
    }
    fmt.Printf("您的全名是: %s %s\n", firstName, lastName)

    var item string
    var quantity int
    fmt.Print("请输入商品名称和数量(例如:苹果 10): ")
    // 匹配一个字符串和一个整数
    _, err = fmt.Scanf("%s %d\n", &item, &quantity)
    if err != nil {
        fmt.Println("读取商品信息时发生错误:", err)
        return
    }
    fmt.Printf("您购买了 %d 个 %s\n", quantity, item)
}

与 fmt.Sscanln 的区别 需要特别注意的是,fmt.Scanf是从标准输入读取数据,而fmt.Sscanln(以及fmt.Sscanf)是从一个已存在的字符串中解析数据,而不是从标准输入读取。因此,在需要从控制台获取用户输入时,应使用fmt.Scanln或fmt.Scanf,而不是fmt.Sscanln。

注意事项与常见问题

  1. 指针的重要性: 无论是fmt.Scanln还是fmt.Scanf,当您希望函数将读取到的值赋给某个变量时,都必须传入该变量的指针(例如&myVar)。这是Go语言中传递参数以修改原变量的标准做法。
  2. bufio与fmt的选择:
    • bufio.NewReader提供更底层的控制,适合逐字符、逐行读取,或需要自定义分隔符的场景,并且可以更好地处理错误。
    • fmt.Scanln和fmt.Scanf则更简洁,适合快速获取特定格式的用户输入。
  3. 错误处理: 所有的输入函数都会返回一个错误值。在生产代码中,务必检查并处理这些错误,以提高程序的健壮性。
  4. 输入缓冲: 当使用fmt.Scanf时,如果格式字符串没有完全消耗掉一行输入(例如,只读取了数字但行末还有字符),剩余的字符可能会留在输入缓冲区中,影响后续的读取操作。在某些情况下,可能需要额外处理或清空输入缓冲区。
  5. 开发环境问题: 极少数情况下,如果上述方法在您的环境中仍然出现异常,可能是由于IDE的特定设置、终端模拟器的行为或操作系统层面的某些配置导致。尝试在不同的终端或编译后直接运行可执行文件进行测试。

总结

Go语言提供了多种从标准输入读取数据的方法,每种方法都有其适用场景。bufio.NewReader提供了灵活的缓冲读取能力,适用于需要精细控制输入流的场景。而fmt.Scanln和fmt.Scanf则提供了简洁高效的格式化输入功能。理解并正确使用变量指针是掌握fmt包输入函数的关键。通过本文的指导和示例,开发者可以更好地在Go程序中实现与用户的交互,构建功能完善的控制台应用程序。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

384

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

609

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

351

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

256

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

594

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

520

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

636

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

599

2023.09.22

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

80

2026.01.09

热门下载

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

精品课程

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

共32课时 | 3.6万人学习

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号