go语言中io操作中的 io.Reader 和 io.Writer的获取方法

 更新时间:2024年10月18日 10:12:56   作者:tekin  
在Go语言中,要进行文件io操作,通常需要使用io.Reader或io.Writer对象,获取这些对象的方法包括使用标准库中已实现Read或Write方法的对象,感兴趣的可以了解一下

我们在对文件进行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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go使用TimerController解决timer过多的问题

    Go使用TimerController解决timer过多的问题

    多路复用,实际上Go底层也是一种多路复用的思想去实现的timer,但是它是底层的timer,我们需要解决的问题就过多的timer问题!本文给大家介绍了Go使用TimerController解决timer过多的问题,需要的朋友可以参考下
    2024-12-12
  • golang slice元素去重操作

    golang slice元素去重操作

    这篇文章主要介绍了golang slice元素去重操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Golang TCP粘包拆包问题的解决方法

    Golang TCP粘包拆包问题的解决方法

    这篇文章主要给大家介绍了Golang TCP粘包拆包问题的解决方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Golang具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • 从go语言中找&和*区别详解

    从go语言中找&和*区别详解

    这篇文章主要介绍了从go语言中找&和*区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • 基于Go语言实现应用IP防火墙

    基于Go语言实现应用IP防火墙

    在公司里面经常会听到某应用有安全漏洞问题,没有做安全加固,IP防火墙就是一个典型的安全加固解决方案,下面我们就来学习一下如何使用go语言实现IP防火墙吧
    2023-11-11
  • Go语言排序算法之插入排序与生成随机数详解

    Go语言排序算法之插入排序与生成随机数详解

    从这篇文章开始将带领大家学习Go语言的经典排序算法,比如插入排序、选择排序、冒泡排序、希尔排序、归并排序、堆排序和快排,二分搜索,外部排序和MapReduce等,本文将先详细介绍插入排序,并给大家分享了go语言生成随机数的方法,下面来一起看看吧。
    2017-11-11
  • go语言通过zlib压缩数据的方法

    go语言通过zlib压缩数据的方法

    这篇文章主要介绍了go语言通过zlib压缩数据的方法,实例分析了Go语言中zlib的使用技巧,需要的朋友可以参考下
    2015-03-03
  • 从Context到go设计理念轻松上手教程

    从Context到go设计理念轻松上手教程

    这篇文章主要为大家介绍了从Context到go设计理念轻松上手教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Golang中int, int8, int16, int32, int64和uint区别浅析

    Golang中int, int8, int16, int32, int64和uint区别浅析

    go语言中的int的大小是和操作系统位数相关的,如果是32位操作系统,int类型的大小就是4字节,如果是64位操作系统,int类型的大小就是8个字节,下面这篇文章主要给大家介绍了关于Golang中int, int8, int16, int32, int64和uint区别的相关资料,需要的朋友可以参考下
    2022-11-11
  • Golang实现请求限流的几种办法(小结)

    Golang实现请求限流的几种办法(小结)

    这篇文章主要介绍了Golang实现请求限流的几种办法(小结),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10

最新评论