Go 之从标准输入读取数据的方法

最近刷题的时候,发现大家都喜欢用 bufio.Scanner 或 bufio.Reader 来从标准输入获取数据,遂来了解一下它们的特性。

文中为了调试方便,使用的 strings.NewReader("input string") 暂时替换 os.Stdin,实际从标准输入获取时可直接使用 os.Stdin 进行替换。

bufio.Scanner

简单来讲,bufio.Scanner 是 Go 中一个用于逐个读取输入缓冲区的扫描器,通常与 bufio.Reader 一起使用,bufio.Reader 用于从输入中读取数据,而 bufio.Scanner 则用于逐个读取输入缓冲区的内容。

bufio.Scanner 可以将输入数据分解为逻辑上的行并返回。Scanner 通过定义一个 Split 函数来将输入分解为行,默认是使用的 bufio.ScanLines,也即默认一次 Scan() 操作读取一行数据。

下面是 bufio.Scanner 提供的一些主要方法:

  • func (s *Scanner) Scan() bool,用于读取输入缓冲区中的下一个数据块,并将其保存在内部的缓冲区中。如果读取成功,则返回 true;如果已经读取了所有数据或者发生了错误,则返回 false。
  • func (s *Scanner) Text() string,用于获取内部缓冲区中的文本内容,通常与 Scan() 方法一起使用,用于获取读取的数据。
  • func (s *Scanner) Bytes() []byte,用于获取内部缓冲区中的字节内容,通常与 Scan() 方法一起使用,用于获取读取的数据。
  • func (s *Scanner) Err() error,用于获取在读取输入时发生的错误信息,如果读取过程中没有发生错误,则返回 nil;否则,返回一个非 nil 的错误对象。
  • func (s *Scanner) Buffer(buf []byte, max int), 用于自定义输入缓冲区大小,接受一个 []byte 类型的参数,用于指定缓冲区的大小。
  • func (s *Scanner) Split(split SplitFunc),用于指定一个分割函数,将输入分割成多个数据块,接受一个 func([]byte) bool 类型的参数,该函数在每次读取输入时被调用,用于判断是否需要将当前数据块分割成多个小块。通常用于处理非常大的数据块,以避免内存溢出等问题。

bufio.ScanLines

这个也是用作默认的分隔函数,默认每次 Scan() 读取一行。

package mainimport ("bufio""fmt""strings"
)func main() {// input := os.Stdininput := strings.NewReader("hello world\nsecond line\nend line")scanner := bufio.NewScanner(input)scanner.Split(bufio.ScanLines) // 如果保持默认可不写这一行for scanner.Scan() {fmt.Printf("%#v\n", scanner.Text())}
}
"hello world"
"second line"
"end line

bufio.ScanWords

简单理解,就是每次 Scan() 按照单词进行扫描读取。

package mainimport ("bufio""fmt""strings"
)func main() {// input := os.Stdininput := strings.NewReader("hello world\nsecond line\nend line")scanner := bufio.NewScanner(input)scanner.Split(bufio.ScanWords)for scanner.Scan() {fmt.Printf("%#v\n", scanner.Text())}
}
"hello"
"world"
"second"
"line"
"end"
"line"

bufio.ScanRunes

简单理解,就是每次 Scan() 按照一个字符进行扫描读取(包括汉字等多字节字符)。

package mainimport ("bufio""fmt""strings"
)func main() {// input := os.Stdininput := strings.NewReader("hello好world")scanner := bufio.NewScanner(input)scanner.Split(bufio.ScanRunes)for scanner.Scan() {fmt.Printf("%#v\n", scanner.Text())}
}
"h"
"e"
"l"
"l"
"o"
"好"
"w"
"o"
"r"
"l"
"d"

bufio.ScanBytes

简单理解,就是每次 Scan() 按照一个字节进行扫描读取(特殊字符如汉字等多字节字符会被分成多次才能读取完成)。

package mainimport ("bufio""fmt""strings"
)func main() {// input := os.Stdininput := strings.NewReader("hello好world")scanner := bufio.NewScanner(input)scanner.Split(bufio.ScanBytes)for scanner.Scan() {fmt.Printf("%#v\n", scanner.Text())}
}
"h"
"e"
"l"
"l"
"o"
"\xe5"
"\xa5"
"\xbd"
"w"
"o"
"r"
"l"
"d"

自定义分隔函数

我们也可以自定义分隔函数,比如说使用逗号进行分隔。

package mainimport ("bufio""fmt""strings"
)func main() {// input := os.Stdininput := strings.NewReader("hello,world")scanner := bufio.NewScanner(input)scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {// 分隔符为逗号for i, d := range data {if d == ',' {return i + 1, data[:i], nil}}if atEOF && len(data) > 0 {return len(data), data, nil}return 0, nil, nil})for scanner.Scan() {fmt.Printf("%#v\n", scanner.Text())}
}
"hello"
"world"

bufio.Reader

reader.ReadLine()

按行读取,但是记得读取的行不包括换行符本身哟。

package mainimport ("bufio""fmt""strings"
)func main() {// read := os.Stdinread := strings.NewReader("hello world\nsecond line\nend line")reader := bufio.NewReader(read)for {s, _, _ := reader.ReadLine()if s == nil {break}fmt.Printf("%#v\n", string(s))}
}

reader.ReadString()

ReadString() 需要自己指定读取的分隔符,比如 \n ,且读取的结果会包含分隔符本身,所以一般按照 \n 读取以后,需要使用 strings.TrimSpace()去掉字符串两端的空白。

package mainimport ("bufio""fmt""strings"
)func main() {// read := os.Stdinread := strings.NewReader("hello world\n\rsecond line\nend line")reader := bufio.NewReader(read)for {s, _ := reader.ReadString('\n')if s == "" {break}fmt.Printf("%#v\n", s)// fmt.Printf("%#v\n", strings.TrimSpace(s))}
}
"hello world\n"
"\rsecond line\n"
"end line"

reader.ReadRune()

package mainimport ("bufio""fmt""strings"
)func main() {// read := os.Stdinread := strings.NewReader("hello好world")reader := bufio.NewReader(read)for {s, _, _ := reader.ReadRune()if s == 0 {break}fmt.Printf("%#v\n", string(s))}
}
"h"
"e"
"l"
"l"
"o"
"好"
"w"
"o"
"r"
"l"
"d"

reader.ReadByte()

package mainimport ("bufio""fmt""strings"
)func main() {// read := os.Stdinread := strings.NewReader("hello好world")reader := bufio.NewReader(read)for {s, _ := reader.ReadByte()if s == 0 {break}fmt.Printf("%#v\n", s)}
}
0x68
0x65
0x6c
0x6c
0x6f
0xe5
0xa5
0xbd
0x77
0x6f
0x72
0x6c
0x64

fmt.Scan 

fmt.Scan

读取由空白符分隔的值保存到传递给参数,换行符视为空白符。

package mainimport ("fmt"
)func main() {var (name    stringage     intmarried bool)fmt.Scan(&name, &age, &married) // 读取由空白符分隔的值保存到传递给本函数的参数中,换行符视为空白符。fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)// 输入:Looking 29 true// 输出:扫描结果 name:Looking age:29 married:true
}

fmt.Scanf

根据 format 参数指定的格式去读取值保存传递给参数。

package mainimport ("fmt"
)func main() {var (name    stringage     intmarried bool)fmt.Scanf("1:%s 2:%d 3:%t", &name, &age, &married) // 根据format参数指定的格式去读取值保存到传递给本函数的参数中。fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)// 输入:1:Looking 2:29 3:true// 输出:扫描结果 name:Looking age:29 married:true
}

fmt.Scanln

Scanln 类似 Scan,它在遇到换行时才停止扫描。

package mainimport ("fmt"
)func main() {var (name    stringage     intmarried bool)fmt.Scanln(&name, &age, &married) // Scanln类似Scan,它在遇到换行时才停止扫描。fmt.Printf("扫描结果 name:%s age:%d married:%t \n", name, age, married)// 输入:Looking 29 true// 输出:扫描结果 name:Looking age:29 married:true
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/812599.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从吉客云到MySQL通过接口配置打通数据

从吉客云到MySQL通过接口配置打通数据 数据源系统:吉客云 吉客云是基于“网店管家”十五年电商ERP行业和技术积累基础上顺应产业发展需求,重新定位、全新设计推出的换代产品,从业务数字化和组织数字化两个方向出发,以构建流程的闭环为依归&am…

大数据入门之如何利用Phoenix访问Hbase

在大数据的世界里,HBase和Phoenix可谓是一对黄金搭档。HBase以其高效的列式存储和强大的数据扩展能力,成为大数据存储领域的佼佼者;而Phoenix则以其SQL化的操作方式,简化了对HBase的访问过程。今天,就让我们一起看看如…

Groovy快速入门

Groovy是一种面向对象的、动态类型的、基于JVM的编程语言,它与Java高度兼容,同时引入了许多简洁、灵活的语法特性,使得开发更为高效。以下是Groovy的快速入门指南: 一. 环境准备 1. 安装Java Development Kit (JDK) Groovy是基于…

学习笔记-微服务基础(黑马程序员)

框架 spring cloudspring cloud alibaba Eureka eureka-server 注册中心 eureka-client 客户端每30s发送心跳服务 服务消费者服务提供者 server 依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-star…

牛客挑战赛74(A,B,C,D)

比赛链接 这场纯纯shit&#xff0c;C是大讨论&#xff0c;D是大模拟。 A 硫酸钡之梦 思路&#xff1a; 发现我们到达第 i i i 个位置的时候&#xff0c;状态其实只有 3 3 3 个&#xff0c;取了的个数-未取的个数-1&#xff0c;0或1。而前面的选取方式不会影响到后面的选取…

Pandas部分应掌握的重要知识点

目录 Pandas部分应掌握的重要知识点一、DataFrame数据框的创建1、直接基于二维数据创建&#xff08;同时使用index和columns参数&#xff09;2、基于excel文件中的数据来创建 二、查看数据框中的数据和联机帮助信息1、查看特殊行的数据2、查看联机帮助的两种常见方法&#xff0…

JavaScript教程(八)--- 正则表达式

正则表达式 正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript 中&#xff0c;正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法&#xff0c;以及 String 的 match、matchAll、replace、search 和 split 方法。本章介绍 JavaScript 正则表达式。 创…

image with CV

""" 视觉&#xff1a;基本API应用&#xff08;OPENCV&#xff09; """ import cv2 import numpy as np"""图像读取方式3. 1.cv2.imread(filename or path, flags)flags0:灰度图像&#xff1b;flags1表示RGB图像&#xff1b;fl…

2024年mathorcup(妈妈杯)数学建模C题思路-物流网络分拣中心货量预测及人员排班

# 1 赛题 C 题 物流网络分拣中心货量预测及人员排班 电商物流网络在订单履约中由多个环节组成&#xff0c;图 ’ 是一个简化的物流 网络示意图。其中&#xff0c;分拣中心作为网络的中间环节&#xff0c;需要将包裹按照不同 流向进行分拣并发往下一个场地&#xff0c;最终使包裹…

JavaScript教程(十三)--- 使用 Promise

使用 Promise Promise 是一个对象&#xff0c;它代表了一个异步操作的最终完成或者失败。因为大多数人仅仅是使用已创建的 Promise 实例对象&#xff0c;所以本教程将首先说明怎样使用 Promise&#xff0c;再说明如何创建 Promise。 本质上 Promise 是一个函数返回的对象&…

《黑马点评》Redis高并发项目实战笔记(上)P1~P43

P1 Redis企业实战课程介绍 P2 短信登录 导入黑马点评项目 首先在数据库连接下新建一个数据库hmdp&#xff0c;然后右键hmdp下的表&#xff0c;选择运行SQL文件&#xff0c;然后指定运行文件hmdp.sql即可&#xff08;建议MySQL的版本在5.7及以上&#xff09;&#xff1a; 下面这…

ArrayList部分底层源码分析

JDK版本为1.8.0_271&#xff0c;以插入和删除元素为例&#xff0c;部分源码如下&#xff1a; // 部分属性 transient Object[] elementData; // 底层数组 private int size; // 记录元素个数 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA {}; // 空Obje…

数据结构2:基于顺序表的通讯录项目

文章目录 头文件SeqList.hContact.h 实现文件SeqList.cContact.c 测试文件text.c 头文件 SeqList.h #pragma once#include<stdio.h> #include<stdlib.h> #include<assert.h> #include"Contact.h"#define INIT_CAPACITY 4//将顺序表数据类型调整为…

基于可变形卷积的大规模视觉基础模型的探索

基于可变形卷积的大规模视觉基础模型的探索 文章目录 基于可变形卷积的大规模视觉基础模型的探索一、简介二、亮点三、项目功能四、模型的应用1、图像模态任务性能2. 图文跨模态任务性能 五、源程序下载 一、简介 本模型包括大规模视觉基础模型"InternImage"&#x…

物联网实战--驱动篇之(五)TEA和AES加密算法

目录 一、前言 二、TEA算法 三、AES算法 四、加解密测试 五、安全性保障 一、前言 物联网的安全性是经常被提及的一个点&#xff0c;如果你的设备之间通讯没有加密的话&#xff0c;那么攻击者很容易就能获取并解析出报文的协议&#xff0c;从而根据攻击者的需要进行设备操…

MongoDB的安装和使用

1.MongoDB 安装 1.1 基于Docker安装 docker run --restartalways -d --name mongo -v /opt/mongodb/data:/data/db -p 27017:27017 mongo:4.0.6 1.2 客户端工具使用 MongoDB Compass | MongoDB 2.MongoDB 使用 2.1 引用依赖包 <dependency><groupId>org.sprin…

信号完整性的常见术语概念(面试常用)

目录 术语 概念一览 1&#xff0e;信号完整性&#xff08;Signal Integrity&#xff09; 2&#xff0e;传输线&#xff08;Transmission Line&#xff09; 3&#xff0e;特性阻抗&#xff08;Characteristic Impedance&#xff09; 4&#xff0e;反射&#xff08;Reflecti…

【环境搭建】ubuntu工作站搭建全流程(显卡4090)

安装ubuntu22.04系统 首先&#xff0c;先压缩windows分区&#xff0c;按住Win X快捷键&#xff0c;选择磁盘管理,压缩分区&#xff0c;压缩出新的分区用于安装ubuntu22.04 windows插入系统盘&#xff0c;点击重启&#xff0c;一直按F12,选择系统盘启动方式语言选择chinese–…

[react优化] 避免组件或数据多次渲染/计算

代码如下 点击视图x➕1,导致视图更新, 视图更细导致a也重新大量计算!!这很浪费时间 function App() {const [x, setX] useState(3)const y x 2console.log(重新渲染, x, y);console.time(timer)let a 0for (let index 0; index < 1000000000; index) {a}console.timeE…

【小红书校招场景题】12306抢票系统

1 坐过高铁吧&#xff0c;有抢过票吗。你说说抢票系统对于后端开发人员而言会有哪些情况&#xff1f; 对于后端开发人员来说&#xff0c;开发和维护一个高铁抢票系统&#xff08;如中国的12306&#xff09;会面临一系列的挑战和情况。这些挑战主要涉及系统的性能、稳定性、数据…