文章目录
前言
Go语言中,为了方便开发者使用,将IO操作封装在了如下几个包中:
- io为IO原语(I/O primitives)提供基本的接口
- io/ioutil封装一些实用的I/O函数
- fmt实现格式化I/O
- bufio实现带缓冲I/O
其中io包中提供I/O原始操作的一系列接口。它主要包装了一些已有的实现,如 os 包中的那些,并将这些抽象成为实用性的功能和一些其他相关的接口。
一 错误变量
-
var EOF = errors.New(“EOF”)
正常输入结束Read返回EOF,如果在一个结构化数据流中EOF在不期望的位置出现了,则应返回错误ErrUnexpectedEOF或者其它给出更多细节的错误。 -
var ErrClosedPipe = errors.New(“io: read/write on closed pipe”)
当从一个已关闭的Pipe读取或者写入时,会返回ErrClosedPipe。 -
var ErrNoProgress = errors.New(“multiple Read calls return no data or error”)
某些使用io.Reader接口的客户端如果多次调用Read都不返回数据也不返回错误时,就会返回本错误,一般来说是io.Reader的实现有问题的标志。 -
var ErrShortBuffer = errors.New(“short buffer”)
ErrShortBuffer表示读取操作需要大缓冲,但提供的缓冲不够大。 -
var ErrShortWrite = errors.New(“short write”)
ErrShortWrite表示写入操作写入的数据比提供的少,却没有显式的返回错误。 -
var ErrUnexpectedEOF = errors.New(“unexpected EOF”)
ErrUnexpectedEOF表示在读取一个固定尺寸的块或者数据结构时,在读取未完全时遇到了EOF。
二 基础接口
2.1 Reader接口
type Reader interface {
Read(p []byte) (n int, err error)
}
Read 将 len§ 个字节读取到 p 中。它返回读取的字节数 n(0 <= n <= len§)以及任何遇到的错误。即使 Read 返回的 n < len§,它也会在调用过程中使用 p的全部作为暂存空间。若一些数据可用但不到 len§ 个字节,Read 会照例返回可用的东西,而不是等待更多。
当 Read 在成功读取 n > 0 个字节后遇到一个错误或 EOF 情况,它就会返回读取的字节数。它会从相同的调用中返回(非nil的)错误或从随后的调用中返回错误(和 n == 0)。这种一般情况的一个例子就是 Reader 在输入流结束时会返回一个非零的字节数,可能的返回不是 err == EOF 就是 err == nil。无论如何,下一个 Read 都应当返回 0, EOF。
调用者应当总在考虑到错误 err 前处理 n > 0 的字节。这样做可以在读取一些字节,以及允许的 EOF 行为后正确地处理I/O错误。
Read 的实现会阻止返回零字节的计数和一个 nil 错误,调用者应将这种情况视作空操作。
实例演示:
package main
import (
"fmt"
"io"
"os"
)
func main() {
f, err := os.Open("a.txt")
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
defer f.Close()
buf := make([]byte, 12) // 实例化一个长度为4的[]byte
for {
n, err2 := f.Read(buf) // 将内容读至buf
if n == 0 || err2 == io.EOF {
fmt.Println("文件以读取完毕")
break
}
fmt.Println(string(buf[:n]))
}
}
运行结果:
[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
hello world
文件以读取完毕
[Done] exited with code=0 in 0.931 seconds
其中a.txt内容为:
hello world
2.2 Writer接口
type Writerinterface {
Write(p []byte) (n int, err error)
}
Write 将 len§ 个字节从 p 中写入到基本数据流中。它返回从 p 中被写入的字节数n(0 <= n <= len§)以及任何遇到的引起写入提前停止的错误。若 Write 返回的n < len§,它就必须返回一个非nil的错误。Write 不能修改此切片的数据,即便它是临时的。
实例演示:
package main
import (
"os"
)
func main() {
f, _ := os.OpenFile("a.txt", os.O_RDWR|os.O_APPEND, 0775) // 以读写模式打开文件,并且在写操作时将数据附加到文件尾部
f.Write([]byte(" hello golang"))
f.Close()
}
运行结果:
a.txt内容更新为:
hello world hello golang
其中a.txt初始内容为:
hello world
2.3 Seeker接口
type Seeker interface {
Seek(offset int64, whence int) (int64, error)
}
Seeker 用来移动数据的读写指针
Seek 设置下一次读写操作的指针位置,每次的读写操作都是从指针位置开始的
-
whence 的含义:
- 如果 whence 为 0:表示从数据的开头开始移动指针
- 如果 whence 为 1:表示从数据的当前指针位置开始移动指针
- 如果 whence 为 2:表示从数据的尾部开始移动指针
-
offset 是指针移动的偏移量
返回移动后的指针位置和移动过程中遇到的任何错误
实例演示:
package main
import (
"fmt"
"os"
)
func main() {
f, _ := os.Open("a.txt") // 打开文件后,光标默认在文件开头
f.Seek(3, 0) // 从索引值为3处开始读
buf := make([]byte, 10) // 设置缓冲区
n, _ := f.Read(buf) // 将内容读到缓冲区内
fmt.Printf("n: %v\n", n)
fmt.Printf("string(buf): %v\n", string(buf))
f.Close()
}
运行结果:
[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
n: 9
string(buf): llo world
[Done] exited with code=0 in 1.526 seconds
其中a.txt内容为:
hello world
2.4 Closer接口
type Closer interface {
Close() error
}
Closer关闭的接口, 带有Close() 方法, 但是行为没有定义,所以 可以特定行为来实现
在整个标准库内都没有对Closer的引用,只有实现,用法都是开启某某连接/流,在用完/报错后在进行Close的操作。
三 组合接口
组合接口是对多个接口进行了组合,当同时实现多个接口时,可以使用组合接口进行传递
3.1 ReadWriter接口
type ReadWriter interface {
Reader
Writer
}
ReadWriter接口聚合了基本的读写操作。
3.2 ReadCloser接口
type ReadCloser interface {
Reader
Closer
}
ReadCloser就是Reader+Closer,例如在ioutil中的NopCloser方法返回的就是一个ReadCloser,但是里面的Close就是个空函数,毫无作用。
3.3 WriteCloser接口
type WriteCloser interface {
Writer
Closer
}
WriteCloser接口聚合了基本的写入和关闭操作。
3.4 ReadWriteCloser接口
type ReadWriteCloser interface {
Reader
Writer
Closer
}
ReadWriteCloser接口聚合了基本的读写和关闭操作。
3.5 ReadSeeker接口
type ReadSeeker interface {
Reader
Seeker
}
ReadSeeker接口聚合了基本的读取和移位操作。
3.6 WriteSeeker接口
type WriteSeeker interface {
Writer
Seeker
}
WriteSeeker接口聚合了基本的写入和移位操作。
3.7 ReadWriteSeeker接口
type ReadWriteSeeker interface {
Reader
Writer
Seeker
}
ReadWriteSeeker接口聚合了基本的读写和移位操作
四 指定读写器读写接口
4.1 ReaderFrom接口
type ReaderFrom interface {
ReadFrom(r Reader) (n int64