我们在对文件进行io操作的时候,经常看到需要我们传递一个 io.reader 或者 io.writer 对象作为读写的入参, 那么我们该如何或者这些个rw对象呢? 其实很简单,你只需要查找一下哪些对象实现了 read或者 writer方法,那么你只需要创建一个实现了这2个方法之一的对象 , 那他就可以是一个 io.reader 或者 io.writer 。
当然最常见的应该就是我们的 os.file对象了, 另外还有 bufio.reader, bytes.buffer 等对象都可以作为io的rw入参。
当然你也可以自己定义一个对象,实现 io.reader 或者 io.writer 接口中定义的方法,那么你的对象也可以作为一个rw入参来使用了。 这个也就是go语言中面向接口编程的完美体现。
go中reader writer接口定义
type reader interface {
read(p []byte) (n int, err error)
}
type writer interface {
write(p []byte) (n int, err error)
}os.file对象中的rw实现代码
// read reads up to len(b) bytes from the file and stores them in b.
// it returns the number of bytes read and any error encountered.
// at end of file, read returns 0, io.eof.
func (f *file) read(b []byte) (n int, err error) {
if err := f.checkvalid("read"); err != nil {
return 0, err
}
n, e := f.read(b)
return n, f.wraperr("read", e)
}
// write writes len(b) bytes from b to the file.
// it returns the number of bytes written and an error, if any.
// write returns a non-nil error when n != len(b).
func (f *file) write(b []byte) (n int, err error) {
if err := f.checkvalid("write"); err != nil {
return 0, err
}
n, e := f.write(b)
if n < 0 {
n = 0
}
if n != len(b) {
err = io.errshortwrite
}
epipecheck(f, e)
if e != nil {
err = f.wraperr("write", e)
}
return n, err
}
bufio.reader中的rw实现代码
// read reads data into p.
// it returns the number of bytes read into p.
// the bytes are taken from at most one read on the underlying reader,
// hence n may be less than len(p).
// to read exactly len(p) bytes, use io.readfull(b, p).
// if the underlying reader can return a non-zero count with io.eof,
// then this read method can do so as well; see the [io.reader] docs.
func (b *reader) read(p []byte) (n int, err error) {
n = len(p)
if n == 0 {
if b.buffered() > 0 {
return 0, nil
}
return 0, b.readerr()
}
if b.r == b.w {
if b.err != nil {
return 0, b.readerr()
}
if len(p) >= len(b.buf) {
// large read, empty buffer.
// read directly into p to avoid copy.
n, b.err = b.rd.read(p)
if n < 0 {
panic(errnegativeread)
}
if n > 0 {
b.lastbyte = int(p[n-1])
b.lastrunesize = -1
}
return n, b.readerr()
}
// one read.
// do not use b.fill, which will loop.
b.r = 0
b.w = 0
n, b.err = b.rd.read(b.buf)
if n < 0 {
panic(errnegativeread)
}
if n == 0 {
return 0, b.readerr()
}
b.w += n
}
// copy as much as we can
// note: if the slice panics here, it is probably because
// the underlying reader returned a bad count. see issue 49795.
n = copy(p, b.buf[b.r:b.w])
b.r += n
b.lastbyte = int(b.buf[b.r-1])
b.lastrunesize = -1
return n, nil
}
// writebuf writes the reader's buffer to the writer.
func (b *reader) writebuf(w io.writer) (int64, error) {
n, err := w.write(b.buf[b.r:b.w])
if n < 0 {
panic(errnegativewrite)
}
b.r += n
return int64(n), err
}
bytes.buffer中的rw实现代码
// read reads the next len(p) bytes from the buffer or until the buffer
// is drained. the return value n is the number of bytes read. if the
// buffer has no data to return, err is io.eof (unless len(p) is zero);
// otherwise it is nil.
func (b *buffer) read(p []byte) (n int, err error) {
b.lastread = opinvalid
if b.empty() {
// buffer is empty, reset to recover space.
b.reset()
if len(p) == 0 {
return 0, nil
}
return 0, io.eof
}
n = copy(p, b.buf[b.off:])
b.off += n
if n > 0 {
b.lastread = opread
}
return n, nil
}
// write appends the contents of p to the buffer, growing the buffer as
// needed. the return value n is the length of p; err is always nil. if the
// buffer becomes too large, write will panic with errtoolarge.
func (b *buffer) write(p []byte) (n int, err error) {
b.lastread = opinvalid
m, ok := b.trygrowbyreslice(len(p))
if !ok {
m = b.grow(len(p))
}
return copy(b.buf[m:], p), nil
}注意这些方法一般是绑定在指针类型的对象上, 所以你在创建你需要的rw对象的时候需要使用&指针符号或者使用 new函数来创建对象, 如:w := &bytes.buffer{} 等效于 w := new(bytes.buffer)
到此这篇关于go语言中io操作中的 io.reader 和 io.writer的获取方法的文章就介绍到这了,更多相关go io.reader io.writer内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论