专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > Go

io 包的惯用接口速记

发布时间:2011-06-29 18:28:42 文章来源:www.iduyao.cn 采编人员:星星草
io 包的常用接口速记

我没有 C/C++ 基础,没有接口的概念,且从 Python 投奔而来,Python 的极简主义(一个结果往往只提供一个方法),让我在 Golang 中非常迷糊,特别是文件的读写操作,因为 Go 的文件读写操作有很多的方法,让我不知道怎么选择。直到我学习了 interface 的概念,然后由看了 package io 后才慢慢理解,也渐渐的喜欢上了 Golang 的灵活性。以我的经验来说,接口是一个很重要的知识点,是一系列操作的规范,特别是公共接口尤为重要,如:package io

本文仅仅为了速记最常用的几个接口,如果您想系统的学习 io 接口,建议阅读底部参考链接。


一、IO 接口概述

package os 提供了对 I/O 原语的基本接口,使之成为共享的公共接口,这些公共接口抽象出了泛用的函数并附加了一些相关的原语的操作。因为这些接口和原语是对底层实现完全不同的低水平操作的包装,除非得到其它方面的通知,客户端不应假设它们是并发执行安全的。

package os 中最重要的是两个接口:Reader 和 Writer 接口。本章所提到的各种接口,都跟这两个接口有关,也就是说,只要实现了这两个接口,它就有了 IO 的功能。

小贴士:
var EOF = errors.New("EOF"): 在 package io中定义,使用非常频繁。正常情况下当 Read() 无法得到更多返回时就返回 EOF,即文件到达了结尾(end-of-file)。

二、io.Reader 和 io.Writer

定义:

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

Read 将 len(p) 个字节读取到 p 中,当遇到任何错误(包括EOF)会立即返回已读取的字节数,函数结束会返回成功读取的字节数和任何错误。
Write 将 len(p) 字节数据从 p 写入底层的数据流,然后返回成功写入的字节数和任何错误。

  • 从接口名称很容易猜到,一般地,Go中接口的命名约定:接口名以er结尾。注意,这里并非强行要求,你完全可以不以 er 结尾。标准库中有些接口也不是以 er 结尾的。

示例:

func wr() {
	f, _ := os.Create("at.txt")
	defer f.Close()
	f.Write([]byte("Go是一种令人愉悦的编程语言")) //写入字节流
	f.Seek(0, os.SEEK_SET)            //将指针重置

	p := make([]byte, 2) // 读取 2 byte( len(buf)=2 )
	if _, err := f.Read(p); err != nil {
		log.Fatal("[F]", err)
	}
	fmt.Printf("读取字符 \"%s\", 长度为 %d byte\n", p, len(p))

	p = make([]byte, 50)
	if _, err := f.Read(p); err != nil {
		if err != io.EOF { //忽略 EOF 错误
			log.Fatal("[F]", err)
		}
	}
	fmt.Printf("读取字符 \"%s\", 长度为 %d byte\n", p, len(p))
}

读取字符 "Go", 长度为 2 byte
读取字符 "是一种令人愉悦的编程语言              ", 长度为 50 byte

三、io.ReaderAt 和 os.WriterAt

定义(off 是 offset 的缩写):

type ReaderAt interface {
    ReadAt(p []byte, off int64) (n int, err error)
}

type WriterAt interface {
    WriteAt(p []byte, off int64) (n int, err error)
}

ReadAt() 从基本输入源的偏移量 off 处开始,其他和 Read() 一样;
WriteAt() 从基本输入源的偏移量 off 处开始,其他和 Write() 一样。

示例:

func at() {
	f, _ := os.Create("at.txt")
	defer f.Close()

	f.WriteString("Go是一种令人愉悦的编程语言")
	f.WriteAt([]byte("程序"), 26) //偏移 26byte 改写“编程”->“程序”

	fi, _ := f.Stat()              //获取文件信息
	p := make([]byte, fi.Size()-2) //文件大小减去偏移值
	f.ReadAt(p, 2)                 //偏移 2 byte

	os.Stdout.Write(p)
}

是一种令人愉悦的编程语言

四、io.ReaderFrom 和 os.WriterTo

定义:

type ReaderFrom interface {
    ReadFrom(r Reader) (n int64, err error)
}

type WriterTo interface {
    WriteTo(w Writer) (n int64, err error)
}

ReadFrom() 从 r 中读取数据,直到 EOF 或发生错误。返回读取的字节数和 io.EOF 之外的其他错误。ReadFrom不会返回EOF错误
WriteTo() 将数据写入 w 中,直到没有数据可写或发生错误。返回写入的字节数和任何错误。

示例:

func fromTo() {
	r := strings.NewReader("Go是一种令人愉悦的编程语言") //创建一个 Reader
	w := bufio.NewWriter(os.Stdout)          //创建一个 Writer

	w.ReadFrom(r) // w 一次性读取 r 的全部内容
	w.Flush()

	r.Seek(0, os.SEEK_SET) //重置指针

	r.WriteTo(w) // r 一次性将内容写入 w 中
	w.Flush()
}

Go是一种令人愉悦的编程语言Go是一种令人愉悦的编程语言

五、io.Seeker

定义:

type Seeker interface {
    Seek(offset int64, whence int) (ret int64, err error)
}

Seek 设置下一次 Read 或 Write 的偏移量(offset),它的解释取决于 whence。示例见上文。

whence的值,在os包中定义了相应的常量:

  • SEEK_SET int = 0 //从文件的起始处开始设置 offset
  • SEEK_CUR int = 1 //从文件的指针的当前位置处开始设置 offset
  • SEEK_END int = 2 //从文件的末尾处开始设置 offset

六、io.Closer

定义:

type Closer interface {
    Close() error
}

用于关闭数据流,释放资源,不用多废话了吧。

七、其他

type ByteReader interface {
	ReadByte() (c byte, err error)
}

type RuneReader interface {
    ReadRune() (r rune, size int, err error)
}

ReadByte读取输入中的单个字节并返回。如果没有字节可读取,会返回错误。
ReadRune读取单个utf-8编码的字符,返回该字符和它的字节长度。如果没有有效的字符,会返回错误。

type ByteWriter interface {
    WriteByte(c byte) error
}

WriteByte写入一个字节,如果写入失败会返回错误。

参考

https://gowalker.org/io
https://github.com/polaris1119/The-Golang-Standard-Library-by-Example/blob/master/chapter01/01.1.md

友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

  • ModernUI课程:定义一个Logo

    ModernUI教程:定义一个Logo ModernWindow的标题栏包含了一块区域用来显示自定义的窗体Logo: 这个窗体logo通过ModernWindow.LogoD...

  • Django忘记管理员账号和密码的解决方法

    Django忘记管理员账号和密码的解决办法 看着Django的教程学习搭建网站,结果忘记第一次创建的账号和密码了。结果搭建成功以后,一直...

  • GO语言小结(1)——基本知识

    GO语言总结(1)——基本知识 1、注释(与C++一样)   行注释://  块注释:/*   ...  */ 2、标识符   可以这么说,除了数字开头...

  • golang 惯用的文件读取方式

    golang 常用的文件读取方式 Golang 的文件读取方法很多,刚上手时不知道怎么选择,所以贴在此处便后速查。 一次性读取 小文件推荐一...

  • 查询深圳市通相关信息

    查询深圳通相关信息 用 HTTP.GET 从开放 API 中查询深圳通信息,然后将 JSON 数据存入结构体中,再格式化输出。 注意:获取的并不是实...

  • Go语言设计模式实践:结合(Composite)

    Go语言设计模式实践:组合(Composite) 关于本系列 这个系列首先是关于Go语言实践的。在项目中实际使用Go语言也有段时间了,一个体会就...

  • 列出索引和遍历目录

    列出目录和遍历目录 获取目录列表用 ioutil.ReadDir(),遍历目录用 filepath.Walk(),使用方法请参考文章示例。 示例代码: package ma...

  • io 包的惯用接口速记

    io 包的常用接口速记 我没有 C/C++ 基础,没有接口的概念,且从 Python 投奔而来,Python 的极简主义(一个结果往往只提供一个方法),让我在...

  • 代理服务扩充

    代理服务扩展 之前自己实现了一个代理服务,当时考虑的是只要支持SOCKS5就好了,因为我经常用CHROME,配合着SwitchySharp,体验还是很棒...

  • 文件的创造与打开

    文件的创建与打开 文件操作是个很重要的话题,使用也非常频繁,熟悉如何操作文件是必不可少的。Golang 对文件的支持是在 os package ...

热门推荐: