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

这篇具有很好参考价值的文章主要介绍了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 main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	// input := os.Stdin
	input := 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 main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	// input := os.Stdin
	input := 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 main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	// input := os.Stdin
	input := 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 main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	// input := os.Stdin
	input := 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 main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	// input := os.Stdin
	input := 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 main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	// read := os.Stdin
	read := 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 main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	// read := os.Stdin
	read := 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 main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	// read := os.Stdin
	read := 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 main

import (
	"bufio"
	"fmt"
	"strings"
)

func main() {
	// read := os.Stdin
	read := 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 main

import (
	"fmt"
)

func main() {
	var (
		name    string
		age     int
		married 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 main

import (
	"fmt"
)

func main() {
	var (
		name    string
		age     int
		married 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,它在遇到换行时才停止扫描。文章来源地址https://www.toymoban.com/news/detail-852644.html

package main

import (
	"fmt"
)

func main() {
	var (
		name    string
		age     int
		married 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
}

到了这里,关于Go 之从标准输入读取数据的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【GoLang】Go语言几种标准库介绍(二)

    前言 上一篇,我们介绍了 bufio (buffered I/O)库和 bytes 库 ,这篇我们继续介绍剩下的库 几种库 container 库 (封装堆、列表和环形列表等容器) container 包并不是一个独立的包,而是包含了一些子包,如 container/list 、 container/heap 等,用于实现不同类型的容器数据结构。这些数据

    2024年02月04日
    浏览(60)
  • 【Golang】Golang进阶系列教程--Go 语言 map 如何顺序读取?

    Go 语言中的 map 是一种非常强大的数据结构,它允许我们快速地存储和检索键值对。 然而,当我们遍历 map 时,会有一个有趣的现象,那就是输出的键值对顺序是不确定的。 先看一段代码示例: 当我们多执行几次这段代码时,就会发现,输出的顺序是不同的。 首先,Go 语言

    2024年02月14日
    浏览(69)
  • 【GoLang入门教程】Go语言几种标准库介绍(六)

    前言 上一篇,我们介绍了image、IO、math三个库,这篇我们继续介绍剩下的库 几种库 Net库 (网络库,支持 Socket、HTTP、邮件、RPC、SMTP 等) 在 Go 语言的标准库中, net 包提供了对网络操作的支持,包括基本的网络协议、Socket 编程、HTTP 客户端和服务器等。 net 包包含多个子包,其

    2024年02月02日
    浏览(62)
  • 【GoLang入门教程】Go语言几种标准库介绍(四)

    前言 上一篇,我们介绍了debug、encoding、flag三个库,这篇我们继续介绍剩下的库 几种库 fmt库 (格式化操作) 在 Go 语言的标准库中, fmt 包提供了格式化输入输出的功能。 这个包包括了一系列函数,用于将数据格式化为字符串( fmt.Sprintf )、输出到控制台( fmt.Print 、 fmt.Pri

    2024年02月03日
    浏览(106)
  • 【GoLang入门教程】Go语言几种标准库介绍(八)

    强烈推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站:人工智能 前言 上一篇,我们介绍了plugin、reflect、regexp三个库,这篇我们继续介绍剩下的库 几种库 runtime库 ( 运行时接口) 在 Go 语言的标准库中, runtime 包

    2024年01月19日
    浏览(66)
  • 【GoLang入门教程】Go语言几种标准库介绍(五)

    前言 上一篇,我们介绍了fmt、Go、html 三个库,这篇我们继续介绍剩下的库 几种库 image库 (常见图形格式的访问及生成) 在 Go 语言的标准库中, image 包提供了对图像的基本操作和处理功能。 这个包定义了 Image 接口和一些基本的图像类型,同时也包含了一些实现了该接口的具

    2024年02月03日
    浏览(72)
  • 【GoLang入门教程】Go语言几种标准库介绍(七)

    前言 上一篇,我们介绍了Net、OS、path三个库,这篇我们继续介绍剩下的库 几种库 plugin库 (Go 1.7 加入的插件系统。支持将代码编译为插件,按需加载) 在 Go 语言的标准库中, plugin 包提供了对 Go 插件的支持。 插件是一种在运行时加载并与主程序交互的机制,允许程序在不重新

    2024年01月16日
    浏览(87)
  • 【C语言基础考研向】05 scanf读取标准输入超详解

    文章目录 一.scanf函数的原理 样例 问题原因 解决方法 二.多种数据类型混合输入 错误样例 正确样例   C语言未提供输入/输出,其输入和输出是通过标准函数库来实现的。C语言通过scanf函数读取键盘输入, 键盘输入又被称为标准输入 。当scanf函数读取标准输入时,如

    2024年01月22日
    浏览(47)
  • Golang 按行读取文件的 3 种方法

    Golang 是一种现代的编程语言,它具有高效、简洁和可扩展等特点,因此在各种领域广泛应用。在 Golang 中,读取文件是一个常见的操作。在本篇技术博客中,我将介绍如何在 Golang 中按行读取文件。 Golang 中有一个 bufio 包,它提供了 Scanner 类型,可以方便地按行读取文件。我

    2024年02月09日
    浏览(43)
  • Golang 按行读取文件的三种方法

    Golang 是一种现代的编程语言,它具有高效、简洁和可扩展等特点,因此在各种领域广泛应用。在 Golang 中,读取文件是一个常见的操作。在本篇技术博客中,我将介绍如何在 Golang 中按行读取文件。 Golang 中有一个 bufio 包,它提供了 Scanner 类型,可以方便地按行读取文件。我

    2024年02月08日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包