io库
io
中包括了常用的io
流中的函数,并依靠这些函数定义了常用的接口和接口组合。我觉得这是最重要的。
常量(Constants)
const (
SeekStart = 0 // 定位到文件头
SeekCurrent = 1 // 定位到当前读写的位置
SeekEnd = 2 // 定位到文件尾
)
都是用于在文件读写时进行定位的常量,相当于C库中的SEEK_START
,SEEK_SET
和SEEK_END
。
变量(Variables)
var EOF = errors.New("EOF")
表示读到了文件结尾。
需要注意的是,返回EOF时只能直接返回io
库中定义的这个变量,因为在进行EOF的判断时,会直接将返回的error
和EOF进行比较(==)。
var ErrClosedPipe = errors.New("io: read/write on closed pipe")
在关闭了的Pipe
上进行了读或者写
var ErrNoProgress = errors.New("multiple Read calls return no data or error")
一个Reader被多个调用方调用,通常意味着该Reader损坏了。
var ErrShortWrite = errors.New("short write")
读取到了少于请求的数量的字节,但又返回不了一个明确的错误。
var ErrUnexpectedEOF = errors.New("unexpected EOF")
当读取一个固定长度的数据块或者一个结构时,读到中间读到了意料之外的EOF。
接口 (interfaces)
读取和写入
io
库中定义了很多常用的接口,涉及输入输出的类都应当遵循这些接口。
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type ByteReader interface {
ReadByte() (byte, error)
}
type ByteWriter interface {
WriteByte(c byte) error
}
// 读出一个Rune,返回该码点和该码点的字节长度
type RuneReader interface {
ReadRune() (r rune, size int, err error)
}
最常用的就是读写函数,分别是Reader
和Writer
,分别读取和写入slice字节,并返回读取和写入的字节数。
类似的是ByteReader
和ByteWriter
,分别读取和写入一个字节。RuneReader
读出一个unicode码点,但没有RuneWriter
。
其他IO相关的接口
// 从偏移off处读取len(p)字节至p。返回读取的字节或者发生的错误。0 <= n <= len(p)
// 1. n < len(p)时,函数会返回一个非nil的err,解释为什么只读取了n个字节。
// 如果可用的数据不足len(p),ReadAt会阻塞,直到读完了或者发生了错误。
// 2. 如果n == len(p),返回的err == nil 或者err == io.EOF
// 如果这个函数在某个支持Seek的结构体内,Seek设置的偏移不应该影响本函数。
type ReaderAt interface {
ReadAt(p []byte, off int64) (n int, err error)
}
// 将数据写入到w中(使用Writer的Write()方法)
type WriterTo interface {
WriteTo(w Writer) (n int64, err error)
}
// 从r中读取数据(使用Reader的Read()方法)
type ReaderFrom interface {
ReadFrom(r Reader) (n int64, err error)
}
// 将写一个String
type StringWriter interface {
WriteString(s string) (n int, err error)
}
// 在off写数据
type WriterAt interface {
WriteAt(p []byte, off int64) (n int, err error)
}
// 在指定位置进行读或者写
// offset是一个有符号整数,whence有三个可选值:io.SeekStart, io.SeekCurrent, io.SeekEnd
type Seeker interface {
Seek(offset int64, whence int) (int64, error)
}
// 关闭输入输出流
type Closer interface {
Close() error
}
这部分是其他的IO相关的接口,包括:从某个位置读写、从其他流读出或写入、定位流、关闭等。
组合接口成为新接口
// 同时支持ReadByte()和UnreadByte()
type ByteScanner interface {
ByteReader
UnreadByte() error
}
// 同时支持ReadRune()和UnreadRune()
type RuneScanner interface {
RuneReader
UnreadRune() error
}
// 同时有Read和Close
type ReadCloser interface {
Reader
Closer
}
// 同时有Read、Seek
type ReadSeeker interface {
Reader
Seeker
}
// 同时有Read、Seek和Close
type ReadSeekCloser interface {
Reader
Seeker
Closer
}
// 同时有Read和Write
type ReadWriter interface {
Reader
Writer
}
// 同时有Read、Write和Seek
type ReadWriteSeeker interface {
Reader
Writer
Seeker
}
// 同时有Read、Write和Close
type ReadWriteCloser interface {
Reader
Writer
Closer
}
这部分主要是将各个单一函数的接口进行组合(或者扩展)。
函数 (Functions)
拷贝
func Copy(dst Writer, src Reader) (written int64, err error)
func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)
func CopyN(dst Writer, src Reader, n int64) (written int64, err error)
将数据从src写入到dst。如果dst支持ReadFrom的话则使用该API。
需要注意的是,如果拷贝成功的话,返回的err == nil,而不是io.EOF.
读取
func ReadAll(r Reader) ([]byte, error)
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
func ReadFull(r Reader, buf []byte) (n int, err error)
读取功能。
Pipe
func Pipe() (*PipeReader, *PipeWriter)
对应于Linux中的pipe接口,创建一个输入流和输出流,写到输出流中的数据可以从输入流中读出。
PipeReader
type PipeReader struct {
// contains filtered or unexported fields
}
func (r *PipeReader) Close() error
func (r *PipeReader) CloseWithError(err error) error
func (r *PipeReader) Read(data []byte) (n int, err error)
可以读取、关闭、关闭并给Writer
返回一个错误。
Close()
后如果另一端再写会返回io.ErrClosedPipe
. 而CloseWithError
后如果另一端再写会返回传入的err。
Read()
时如果另一端关闭了则会返回io.EOF
.
PipeWriter
type PipeWriter struct {
// contains filtered or unexported fields
}
func (w *PipeWriter) Close() error
func (w *PipeWriter) CloseWithError(err error) error
func (w *PipeWriter) Write(data []byte) (n int, err error)
和PipeReader
有着类似的函数,只不过当写端调用Close()
时,对应的Reader
端读取时返回io.EOF
。
其他
func WriteString(w Writer, s string) (n int, err error)
有StringWriter了还要有个内置的WriteString函数,看来写字符串很常用啊。
生成接口类型的函数
func NopCloser(r Reader) ReadCloser
生成一个ReaderCloser,该ReaderCloser
的Read()
方法来自传入的Reader
,Close()
方法是一个nop(没有操作)。
func MultiReader(readers ...Reader) Reader
func TeeReader(r Reader, w Writer) Reader
MultiReader
将多个Reader
组合,读取时前一个Reader
到了EOF
就继续从下一个Reader
读。
func MultiWriter(writers ...Writer) Writer
和MultiWriter
类似。
结构 (Structures)
type LimitedReader struct {
R Reader // underlying reader
N int64 // max bytes remaining
}
func LimitReader(r Reader, n int64) Reader
func (l *LimitedReader) Read(p []byte) (n int, err error)
限制最多读取N个字节。LimitReader()
生成一个新的LimitReader
结构。
type OffsetWriter struct {
// contains filtered or unexported fields
}
func NewOffsetWriter(w WriterAt, off int64) *OffsetWriter
func (o *OffsetWriter) Seek(offset int64, whence int) (int64, error)
func (o *OffsetWriter) Write(p []byte) (n int, err error)
func (o *OffsetWriter) WriteAt(p []byte, off int64) (n int, err error)
OffsetWriter
能够从指定的偏移处进行写。
NewOffsetWriter()
创建一个新的OffsetWriter
。
Seek()
设置偏移;Write()
进行写入;WriteAt()
在指定偏移进行写入,该方法不受位置影响,都是从初始位置开始计算偏移。
type SectionReader struct {
// contains filtered or unexported fields
}
func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader
func (s *SectionReader) Read(p []byte) (n int, err error)
func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error)
func (s *SectionReader) Seek(offset int64, whence int) (int64, error)
func (s *SectionReader) Size() int64
从r
的off
开始读取,最多读n
个就到EOF
。