我的编程空间,编程开发者的网络收藏夹
学习永远不晚

GOLang IO接口与工具如何使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

GOLang IO接口与工具如何使用

这篇文章主要介绍“GOLang IO接口与工具如何使用”,在日常操作中,相信很多人在GOLang IO接口与工具如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”GOLang IO接口与工具如何使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、io包中接口的好处和优势

1.1拷贝数据的函数

io.Copy(dst Writer, class="lazy" data-src Reader)

io.CopyBuffer(dst Writer, class="lazy" data-src Reader, buf []byte)

io.CopyN(dst Writer, class="lazy" data-src Reader, buf []byte)

class="lazy" data-src := strings.NewReader("CopyN copies n bytes (or unil an error) from class="lazy" data-src to dst." +"It returns the number of bytes copied and " +"the earliest error encountered while copying")dst := new(strings.Builder)written, err := io.CopyN(dst, class="lazy" data-src, 58)if err != nil {fmt.Printf("err: %v\n", err)} else {// Written(58): "CopyN copies n bytes (or unil an error) from class="lazy" data-src to dst.It"fmt.Printf("Written(%d): %q\n", written, dst.String())}

二、在io包中io.Reader的扩展接口和实现类型

2.1 io.Reader的扩展接口

io.ReadWriter 这个接口即是io.Reader的扩展接口,也是io.Writer的扩展接口;

该接口定义了一组行为,包含且仅包含了基本的字节序列读取方法Read,和字节写入方法Write。

io.ReadCloser: 该接口除了包含基本的字节序列读取方法以外,还拥有一个基本的关闭方法Close。

Close方法一般用于关闭数据读写的通道。这个接口其实是io.Reader接口和io.Closer接口的组合。

io.ReadWriteCloser:这个接口是io.Readerio.Writerio.Closer三个接口的组合。

io.ReadSeeker :该接口拥有一个寻找读写位置的基本方法Seek。

该方法可以根据给定的偏移量,基于数据的起始位置、末尾位置、或者当前读写位置去寻找新的读写位置。这个新的读写位置用于表明下一次读或写时的起始索引。

Seek是io.Seeker接口唯一拥有的方法。

io.ReadWriteSeeker:这个接口是io.Readerio.Writerio.Seeker三个接口的组合。

2.2 io.Reader接口的实现类型

*io.LimitedReader:此类型的基本类型会包装io.Reader类型的值,并提供一个额外的受限读取的功能。

该类型的读取方法Read返回的总数据量会受到限制。无论该方法被调用多少次。这个限制由该类型的字段N指明,单位是字节。

*io.SectionReader :此类型的基本类型可以包装io.ReaderAt类型的值,并且会限制它的Read方法,只能读取原始数据的一部分(或者说某一段)。

这个数据段段起始位置和末尾位置,需要在它被初始化的时候就指明,并且之后无法变更。该类型的值的行为与切片有些类型,只会对外暴露在其窗口之中的那些数据。

*io.teeReader:该类型是一个包级私有的数据类型,也是io.TeeReader函数结果值的实际类型。

TeeReader(r Reader, w Writer)函数的结果值的Read方法,会把r中的数据经过作为方法参数的字节切片p写入w中。也就是说,p是r和w的数据搬运工。

teeReader1 := io.TeeReader(class="lazy" data-src, dst)p := make([]byte, 7)teeReader1.Read(p)

*io.multiReader:该类型也是包级私有的数据类型。类似地,io包中有一个名为MultiReader的函数,它可以接受若干个io.Reader类型的参数值,并返回一个实际类型为io.multiReader的结果值。

当这个结果值当Read方法被调用,它会顺序地从前面那些io.Reader类型的参数值中读取数据。因此,我们也称之为多对象读取器。

*io.pipe:此类型是一个包级私有的数据类型。它不但实现了io.Reader接口,而且还实现了io.Writer接口。

实际上,io.PipeReader类型和io.PipeWriter类型拥有的所有指针方法都是以它为基础的。这些方法都是代理了io.pipe类型值所拥有的某一个方法而已。

Pipe() (*PipeReader, *PipeWriter) 返回两个类型的指针值,并分别把它们作为其生成的同步内存管道的两端。所以可以说,*io.pipe类型就是io包提供的同步内存管道的核心实现。

*ip.PipeReader该类型可以被视为*io.pipe类型的代理类型。它代理了后者的一部分功能,并基于后者实现了io.ReadClosed接口。同时,它还定义了同步内存管道的读取端。

在实际的面试中,只要应聘者能够从某一个方面出发,说出io.Reader的扩展接口及其存在意义,或者说清楚该接口的三五个实现类型,那么就可以算是基本回答正确了。

2.3 示例

package mainimport ("fmt""io""strings""sync""time")func executeIfNoErr(err error, f func()) {if err != nil {fmt.Printf("error: %v\n", err)return}f()}func example1(comment string) {// 创建一个字符串// 创建一个字符串读取器,它的名字是 reader1。fmt.Println("创建一个字符串读取器,它的名字是 reader1。")reader1 := strings.NewReader(comment)buf1 := make([]byte, 7)n, err := reader1.Read(buf1)var index1, offset1 int64executeIfNoErr(err, func() {// Read(7): "Package"fmt.Printf("Read(%d): %q\n", n, buf1[:n])offset1 = int64(54)index1, err = reader1.Seek(offset1, io.SeekCurrent)})executeIfNoErr(err, func() {fmt.Printf("基于当前的所以,移动%d的偏移量后,新的索引值为: %d \n", offset1, index1)n, err = reader1.Read(buf1)})executeIfNoErr(err, func() {fmt.Printf("Read(%d):%q\n", n, buf1[:n])})fmt.Println()}func example2(comment string) {reader1 := strings.NewReader(comment)reader1.Reset(comment)num := int64(7)fmt.Printf("创建一个新的限制Reader,限制读的数量为:%d\n", num)reader2 := io.LimitReader(reader1, num)buf2 := make([]byte, 10)for i := 0; i < 3; i++ {n, err := reader2.Read(buf2)executeIfNoErr(err, func() {fmt.Printf("Read(%d):%q\n", n, buf2[:n])})}fmt.Println()}func example3(comment string) {reader1 := strings.NewReader(comment)writer1 := new(strings.Builder)fmt.Println("创建一个新的teeReader, 带有一个reader和一个writer")reader3 := io.TeeReader(reader1, writer1)buf4 := make([]byte, 40)for i := 0; i < 8; i++ {n, err := reader3.Read(buf4)executeIfNoErr(err, func() {fmt.Printf("Read(%d):%q\n", n, buf4[:n])})}fmt.Println()}func example4(comment string) {reader1 := strings.NewReader(comment)offset1 := int64(56)num2 := int64(72)fmt.Printf("创建一个section Reader 带有一个Reader, 偏移量为%d, 数量为 %d...\n", offset1, num2)reader2 := io.NewSectionReader(reader1, offset1, num2)buf1 := make([]byte, 20)for i := 0; i < 5; i++ {n, err := reader2.Read(buf1)executeIfNoErr(err, func() {fmt.Printf("Read(%d): %q\n", n, buf1[:n])})}fmt.Println()}func example5() {reader01 := strings.NewReader("MultiReader returns a Reader that's the logical concatenation of " +"the provided input readers.")reader02 := strings.NewReader("They're read sequentially.")reader03 := strings.NewReader("Once all inputs have returned EOF, " +"Read will return EOF.")reader04 := strings.NewReader("If any of the readers return a non-nil, " +"non-EOF error, Read will return that error.")fmt.Println("创建一个multi-reader, 带有4个reader")reader1 := io.MultiReader(reader01, reader02, reader03, reader04)buf2 := make([]byte, 50)for i := 0; i < 8; i++ {n, err := reader1.Read(buf2)executeIfNoErr(err, func() {fmt.Printf("Read(%d): %q\n", n, buf2[:n])})}fmt.Println()}func example6() {fmt.Println("创建一个新的内存同步管道....")pipeReader, pipWriter := io.Pipe()_ = interface{}(pipeReader).(io.ReadCloser)_ = interface{}(pipWriter).(io.WriteCloser)comments := [][]byte{[]byte("Pipe creates a synchronous in-memory pipe."),[]byte("It can be used to connect code expecting an io.Reader "),[]byte("with code expecting an io.Writer."),}// 这里的同步工具,纯属为了保证下面示例中的打印语句能够执行完成// 在实际中没必要这样做var wg sync.WaitGroupwg.Add(2)go func() {defer wg.Done()for _, d := range comments {time.Sleep(time.Millisecond * 500)n, err := pipWriter.Write(d)if err != nil {fmt.Printf("read error : %v\n", err)break}fmt.Printf("Writen(%d): %q\n", n, d)}pipWriter.Close()}()go func() {defer wg.Done()wBuf := make([]byte, 55)for {n, err := pipeReader.Read(wBuf)if err != nil {fmt.Printf("read error: %v\n", err)break}fmt.Printf("Read(%d): %q\n", n, wBuf[:n])}}()wg.Wait()}func main() {comment := "Package io provides basic interfaces to I/O primitives. " +"Its primary job is to wrap existing implementations of such primitives, " +"such as those in package os, " +"into shared public interfaces that abstract the functionality, " +"plus some other related primitives."// 示例1:: Seekexample1(comment)// 示例2: LimitReaderexample2(comment)// 示例3: TeeReaderexample3(comment)// 示例4: NewSectionReaderexample4(comment)// 示例5: MultiReaderexample5()// 示例6example6()}

三、io包的接口以及它们之间的关系

没有嵌入其它接口并且只定义了一个方法的接口,总共有11个。其中有3个接口有着众多的扩展接口和实现类型,它们是:io.Readerio.Writerio.Closer

可以把这些接口分为四类:读取、写入、关闭、读写位置设定。前三个操作属于基本的I/O操作。

3.1 读操作接口

上面已经讨论,核心接口io.Reader有5个扩展接口,6个实现类型。更多的读操作接口还有:

io.ByteReaderio.RuneReader。它们分别定义了一个读取方法:ReadByteReadRune。用于读取下一个单一的字节和Unicode字符。

var b *bytes.Bufferb = bytes.NewBufferString("ab")_ = interface{}(b).(io.ByteReader)_ = interface{}(b).(io.RuneReader)_ = interface{}(b).(io.ByteScanner)_ = interface{}(b).(io.RuneScanner)// io.ByteReadervar reader01 *strings.Readerreader01 = strings.NewReader("aa")_ = interface{}(reader01).(io.ByteReader)_ = interface{}(reader01).(io.RuneReader)_ = interface{}(reader01).(io.ByteScanner)_ = interface{}(reader01).(io.RuneScanner)

strings.Readerbytes.Buffer都是io.ByteReaderio.RuneReader的实现类型。同时,这两个接口,还都实现了io.ByteScannerio.RuneScanner

type ByteScanner interface {ByteReaderUnreadByte() error}

io.ByteScanner接口内嵌了简单接口io.ByteReader、并额外定义了UnreadByte方法,这样,它就抽象出一个能够读取和读回退单字节的功能集。

type RuneScanner interface {RuneReaderUnreadRune() error}

io.RuneScanner接口内嵌了简单接口io.RunneReader,并额外定义了UnreadRune方法。这样,它就抽象出一个能够读取和读回退单个Unicode字符的功能集。

io.ReaderAt接口只定义了一个方法ReadAt。ReadAt是一个纯粹的只读方法。

它只读其所属值中包含的字节,而不对这个值进行真正的修改。比如,它绝对不能修改已读计数的值。

io.WriterTo接口,定义了一个名为WriteTo的方法。它只会接受一个io.Writer类型的参数值,并从该参数值中读出数据,并写入其所属值中。

与之对应的接口是io.ReaderFrom

io.CopyN函数,在复制数据的时候,会检查其参数class="lazy" data-src,是否实现了io.WriterTo接口。如果是,那么它就直接利用该值的WriteTo方法,把其中的数据拷贝给参数dst参数的值。

类似地,这个函数还会检查dst的值是否实现了io.ReaderFrom接口。如果是,那么它就会利用这个值的ReadFrom方法,直接从class="lazy" data-src那里把数据拷贝到该值。

io.Copyio.CopyBuffer,和io.CopyN一样。因为它们内部复制到时候,使用同一套代码。

3.2 写操作接口

io.ReaderFrom接口,它定义了一个名叫ReadFrom的写入方法。该方法接受一个io.Reader类型的参数值。并会从该参数值中读取数据,并写入到所属值中。

基于io.Writer 扩展的接口

io.ReadWriter

*io.pipe就是io.ReadWriter 接口的实现类型。

io.ReadWriteClose

io.ReadWriteSeeker

io.WriteCloser

io.WriteSeeker

io.ByteWriter

io.WriterAt

*io.File不但是io.WriterAt的实现类型,同时还实现了io.ReadWriterCloserio.ReadWriteSeeker接口。

3.3 读写位置设定接口

io.Seeker接口作为一个读写位置设定相关的接口,仅定义了一个方法,叫Seek

基于io.Seeker扩展的接口:

io.ReadSeeker

io.ReadWriteSeeker

io.WriteSeeker

io.WriteSeeker是基于io.Writerio.Seeker的扩展接口

*strings.Reader*io.SectionReader都实现了io.Seeker接口,这两个类型也都是io.ReaderAt接口的实现类型。

var reader02 *strings.Readerreader02 = strings.NewReader("aa")_ = interface{}(reader02).(io.Seeker)_ = interface{}(reader02).(io.ReaderAt)var sectionReader01 *io.SectionReadersectionReader01 = io.NewSectionReader(reader02, 0, 1)_ = interface{}(sectionReader01).(io.Seeker)_ = interface{}(sectionReader01).(io.ReaderAt)

3.4 关闭操作

io.Closer

它的实现类型,在io包里只有io.PipeReaderio.PipeWriter

四、总结11个简单接口和9个扩展接口

4.1 读取操作接口有5个

io.Reader

io.ByteReader

io.RuneReader

io.ReaderAt

io.WriterTo

4.2 写入操作接口有4个

io.Writer

io.ByteWriter

io.WriterAt

io.ReaderFrom

4.3 关闭操作接口有1个

io.Closer

4.4 读写位置设定的接口有1个

io.Seeker

4.5 基于11简单接口的扩展接口有9个

io.ReadWriter

io.ReadCloser

io.ReadSeeker

io.ByteScanner

io.RuneScanner

io.ReadWriteCloser

io.ReadWriteSeeker

io.WriteCloser

io.WriteSeeker

到此,关于“GOLang IO接口与工具如何使用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

GOLang IO接口与工具如何使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

GOLang IO接口与工具如何使用

这篇文章主要介绍“GOLang IO接口与工具如何使用”,在日常操作中,相信很多人在GOLang IO接口与工具如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”GOLang IO接口与工具如何使用”的疑
2023-07-05

GOLang IO接口与工具使用方法讲解

这篇文章主要介绍了GOLang IO接口与工具使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2023-03-19

Go语言中io/ioutil工具如何使用

今天小编给大家分享一下Go语言中io/ioutil工具如何使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。读取文件读取文件
2023-06-30

如何使用 Golang ORM 工具与数据库交互?

使用 gorm orm 工具与数据库交互,可通过以下步骤轻松实现:安装和初始化(1)、定义模型(2)、建立映射(3)、创建记录(4)、读取记录(5)、更新记录(6)、删除记录(7)、事务处理(8)并 ارائه یک خلاصه از مق
如何使用 Golang ORM 工具与数据库交互?
2024-05-14

如何使用Postman和SoapUI工具测试WebService接口

这篇文章主要讲解了“如何使用Postman和SoapUI工具测试WebService接口”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用Postman和SoapUI工具测试WebSer
2023-06-30

Golang模糊测试工具如何使用

本篇内容介绍了“Golang模糊测试工具如何使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!开发环境升级到Go 1.18Go 1.18虽然
2023-07-05

如何使用工具分析 golang 函数

回答:分析 go 函数需要使用 pprof 和 flamegraph 两个工具。步骤:使用 pprof 生成性能配置文件。可视化配置文件并识别热点函数。使用 flamegraph 生成火焰图。通过火焰图分析函数调用关系。使用 pprof 和
如何使用工具分析 golang 函数
2024-05-07

Golang接口型函数如何使用

这篇文章主要介绍“Golang接口型函数如何使用”,在日常操作中,相信很多人在Golang接口型函数如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang接口型函数如何使用”的疑惑有所帮助!接下来
2023-07-02

Golang指针和接口如何使用

这篇文章主要介绍“Golang指针和接口如何使用”,在日常操作中,相信很多人在Golang指针和接口如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang指针和接口如何使用”的疑惑有所帮助!接下来
2023-07-05

SpringBoot项目如何使用hutool工具进行http接口调用

本文小编为大家详细介绍“SpringBoot项目如何使用hutool工具进行http接口调用”,内容详细,步骤清晰,细节处理妥当,希望这篇“SpringBoot项目如何使用hutool工具进行http接口调用”文章能帮助大家解决疑惑,下面跟
2023-06-30

Golang开发之接口的具体使用详解

在Golang中,接口是一种类型,它是由一组方法签名组成的抽象集合。这篇文章主要为大家介绍了Golang接口的具体使用,希望对大家有所帮助
2023-05-14

如何使用工具生成 Golang 函数文档?

命令 godoc -markdown=index.md 可生成 go 函数文档,通过打开生成的文件 index.md 查看文档。具体步骤为:1. 保存 go 文件;2. 运行命令 godoc -markdown=index.md。如何使用工
如何使用工具生成 Golang 函数文档?
2024-05-06

C/C++程序链接与反汇编工具objdump如何使用

这篇文章主要介绍“C/C++程序链接与反汇编工具objdump如何使用”,在日常操作中,相信很多人在C/C++程序链接与反汇编工具objdump如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C/C++
2023-07-05

Golang接口的定义与空接口及断言怎么使用

这篇文章主要讲解了“Golang接口的定义与空接口及断言怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Golang接口的定义与空接口及断言怎么使用”吧!1. Golang中的接口在G
2023-07-06

如何使用 GoDoc 工具生成 Golang 函数文档?

godoc 工具可以通过以下步骤生成 golang 函数文档:为函数编写包含函数签名和描述的注释。运行 godoc 命令(godoc -http=:6060)生成文档。在浏览器中访问生成的文档(http://localhost:6060/p
如何使用 GoDoc 工具生成 Golang 函数文档?
2024-04-18

git工具如何使用

git工具是一个非常常用的版本控制系统,它可以帮助程序员管理代码,协作开发,以及版本控制,而且非常易于使用。本文将会详细讲解如何使用git工具。一、Git的安装与配置首先,我们要安装Git工具。去官方网站下载对应操作系统的安装包,然后进行安
2023-10-22

Golang接口的定义与空接口及断言的使用示例

在 Golang 中,接口是一种类型,它是由一组方法签名组成的抽象集合。这篇文章主要为大家介绍了Golang接口的具体使用,希望对大家有所帮助,空接口是特殊形式的接口类型,普通的接口都有方法,而空接口没有定义任何方法口,也因此,我们可以说所有类型都至少实现了空接口
2023-05-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录