io包提供了对I/O(input和output,即输入输出)原语的基本接口,它的基本任务是包装这些原语已有的实现(如os包里的原语),使之成为共享的公共接口。比如在 Go 语言标准库 strings、bytes、bufio、和 os 中,都有实现 io.Reader 的类型。本文我们通过IO库定义的接口,一步步加深了解。
先看IO库的代码,src/io/io.go,这里是所有io接口的定义,基础接口和组合接口,但是注意的是这是只是定义了接口语义,并不涉及到接口的具体实现,对于接口的具体实现我们会结合日常遇到的列举一些场景,这里我大概理了一下这些接口的关系,如下图:

图中Reader、Writer、Closer、Seeker接口是基本接口,但是组合类型接口中的ReadWriter等这些是基于这几个,利用匿名方式组合的、然后还有一些独立的接口,比如ReaderFrom。
我们先来看Reader,Reader是包装基本Read方法的接口,Read最多可将len(p)个字节读入p,它返回字节数读取(0<=n<=len(p))和遇到的任何错误。
type Reader interface {
Read(p []byte) (n int, err error)
}Writer是包装基本Write方法的接口,Write将len(p)个字节从p写入底层数据流,它返回从p(0<=n<=len(p))写入的字节数,以及所遇到的导致写入提前停止的任何错误,如果Write返回n<len(p),则它必须返回一个非零错误。在bytes和bufio包都有对他Wirte方法的实现,后面我会贴个图,我们可以根据列出来的结构体去查对于具IO接口的具体实现方法。
type Writer interface {
Write(p []byte) (n int, err error)
}比如ReadWriter就是组合类型的接口,是Reader和Writer接口利用匿名字段组合的,如果要实现ReadWriter接口就要同时实现Reader和Writer接口的方法。
type ReadWriter interface {
Reader
Writer
}Go基于io定义的接口实现有哪些呢,看我总结的图就知道,是不是很熟悉,原来 strings、bytes、os都有很多实现。

bytes.NewReader和strings.NewReader都可以包裹[]byte或者string返回一个实现了所有read相关接口的Reader
// bytes包
func NewReader(b []byte) *Reader
// strings包
func NewReader(s string) *Reader在什么场景会用到呢,比如我们发送一个Post请求,这里body就是我们的待发送数据,是一个io.Reader,
func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *Response, err error)
//strings和bytes调用NewReader
http.Post("http://test.com", "text/plain", strings.NewReader("stings test"))
http.Post("http://test.com", "text/plain", bytes.NewReader([]byte("bytes test"))Go的File文件句柄(File其实是个结构体),File 这个结构体对外实现了 Read,Write,ReadAt,WriteAt 等接口
type File struct {
*file // os specific
}
type file struct {
pfd poll.FD
name string
dirinfo *dirInfo // nil unless directory being read
appendMode bool // whether file is opened for appending
}我们使用os.Open或者os.OpenFile获得File结构体的指针,然后读取打开文件的内容,举个栗子:
file ,err:= os.Open("1.txt")
if err != nil {
return
}
//当函数退出时,及时关闭file句柄
defer file.Close()
//返回 *Reader
reader := bufio.NewReader(file)
//读到换行符就终止
str,err := reader.ReadString('\n')
//NewReader函数
func NewReader(rd io.Reader) *Reader {
return NewReaderSize(rd, defaultBufSize)
}是不是感觉很熟悉,来看代码逻辑,先获得File句柄,因为File实现了IO.Reader接口,所以bufio.NewReader()可以传递file句柄,创建一个缓冲区(默认大小4096),bufio实现了ReadString接口读取缓冲区内容。
Go 的 io 最最核心的是 io 库,如果要实现其中的 interface,还是要多看源码注释,除了定义的接口外,io/ioutil提供的ReadFile、ReadAll函数也是很好用的,同时希望本文能对大家理解Golang的io库有帮助!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。