Go标准库学习:io库
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
。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战