Golang标准库——io-结构

结构

LimitedReader

定义

限制从Reader中读取的字节数。

type LimitedReader struct {
	R Reader // underlying reader
	N int64  // max bytes remaining
}

方法

//Limited
func (l *LimitedReader) Read(p []byte) (n int, err error) {
        //已经读完了返回EOF
	if l.N <= 0 {
		return 0, EOF
	}
	//限制读取的长度
	if int64(len(p)) > l.N {
		p = p[0:l.N]
	}
	//直接调用Reader的Read
	n, err = l.R.Read(p)
	//更新N,保证一个LimitReader限制字节数
	l.N -= int64(n)
	return
}

SectionReader

定义

实现了对底层满足ReadAt接口的输入流某个片段的Read、ReadAt、Seek方法.

type SectionReader struct {
	r     ReaderAt      
	base  int64     //读取的起始偏移
	off   int64     //读取时的指针
	limit int64     //最终位置
}

方法


//读
func (s *SectionReader) Read(p []byte) (n int, err error) {
    //超过limit返回EOF
	if s.off >= s.limit {
		return 0, EOF
	}
	//计算最大可以读取的长度,进而修改slice
	if max := s.limit - s.off; int64(len(p)) > max {
		p = p[0:max]
	}
	//从off开始读取len(p)个字节
	n, err = s.r.ReadAt(p, s.off)
	s.off += int64(n)
	return
}

//跳转后的偏移能大于limit吗??
//Seeker
//返回跳转后与起始位置的偏移
func (s *SectionReader) Seek(offset int64, whence int) (int64, error) {
	switch whence {
	default:
		return 0, errWhence
	case SeekStart:     //SeekStart   = 0 // 相对起始位置跳转
		offset += s.base   
	case SeekCurrent:    //SeekCurrent = 1 // 相对当前位置跳转
		offset += s.off
	case SeekEnd:   //SeekEnd     = 2 // 相对最后位置跳转
		offset += s.limit
	}
	//跳转后偏移必须大于起始位置
	if offset < s.base {
		return 0, errOffset
	}
	s.off = offset
	return offset - s.base, nil
}

//off为相对base偏移量
func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error) {
    //不能大于Size()
	if off < 0 || off >= s.limit-s.base {
		return 0, EOF
	}
	//设置ReadAt的初始位置,该off不能影响SectionReader.off
	off += s.base
	//计算可以读取的长度
	if max := s.limit - off; int64(len(p)) > max {
		p = p[0:max]
		n, err = s.r.ReadAt(p, off)
		//此时len(p)>max,因此需要设置文件结束的err
		if err == nil {
			err = EOF
		}
		return n, err
	}
	//可以直接读取
	return s.r.ReadAt(p, off)
}

func (s *SectionReader) Size() int64 { return s.limit - s.base }

teeReader

定义

私有结构,需要通过TeeReader函数创建一个teeReader,使读取r的数据之前均写入到w中

type teeReader struct {
	r Reader
	w Writer
}

方法

func (t *teeReader) Read(p []byte) (n int, err error) {
    //从r中读数据
	n, err = t.r.Read(p)
	if n > 0 {
	    //想w写入数据
		if n, err := t.w.Write(p[:n]); err != nil {
			return n, err
		}
	}
	return
}

multiReader

定义

通过MultiReader创建,从多个Reader中连续读取

type multiReader struct {
	readers []Reader
}

方法

//实现Reader接口
//从readers中按顺序读取数据
func (mr *multiReader) Read(p []byte) (n int, err error) {
    
	for len(mr.readers) > 0 {
		// Optimization to flatten nested multiReaders (Issue 13558).
		//嵌套multiReader
		if len(mr.readers) == 1 {
			if r, ok := mr.readers[0].(*multiReader); ok {
				mr.readers = r.readers
				continue
			}
		}
		n, err = mr.readers[0].Read(p)
		//判断当前Reader是否读完
		if err == EOF {
			//释放对已读完的Reader的引用
			mr.readers[0] = eofReader{} // permit earlier GC
			//剔除第一个元素
			mr.readers = mr.readers[1:]
		}
		//如果readers还有则不能返回EOF
		if n > 0 || err != EOF {
			if err == EOF && len(mr.readers) > 0 {
				// Don't return EOF yet. More readers remain.
				err = nil
			}
			return
		}
	}
	return 0, EOF
}

multiWriter

定义

通过MultiWriter创建,每次写入数据会同时写入到这一组Writer

type multiWriter struct {
	writers []Writer
}

方法

func (t *multiWriter) Write(p []byte) (n int, err error) {
    //循环写入
	for _, w := range t.writers {
		n, err = w.Write(p)
		//某个报错则返回
		if err != nil {
			return
		}
		//必须将p都写入
		if n != len(p) {
			err = ErrShortWrite
			return
		}
	}
	return len(p), nil
}
//写字符串
func (t *multiWriter) WriteString(s string) (n int, err error) {
	var p []byte // lazily initialized if/when needed
	for _, w := range t.writers {
	    //判断是否实现了stringWriter接口
		if sw, ok := w.(stringWriter); ok {
			n, err = sw.WriteString(s)
		} else {
		    //将string转为slice
			if p == nil {
				p = []byte(s)
			}
			//调用Write
			n, err = w.Write(p)
		}
		if err != nil {
			return
		}
		 //所有Writer必须都写完
		if n != len(s) {
			err = ErrShortWrite
			return
		}
	}
	return len(s), nil
}

pipe

定义

PipeReader和PipeWriter的底层实现

type pipe struct {
	rl    sync.Mutex // gates readers one at a time
	wl    sync.Mutex // gates writers one at a time
	l     sync.Mutex // protects remaining fields
	data  []byte     // data remaining in pending write
	rwait sync.Cond  // waiting reader
	wwait sync.Cond  // waiting writer
	rerr  error      // if reader closed, error to give writes
	werr  error      // if writer closed, error to give reads
}

方法

func (p *pipe) read(b []byte) (n int, err error) {
	// One reader at a time.
	//上Reader的锁
	p.rl.Lock()
	defer p.rl.Unlock()
    //锁其他字段
	p.l.Lock()
	defer p.l.Unlock()
	//死循环直到有数据可读了
	for {
	    //reader关闭了
		if p.rerr != nil {
			return 0, ErrClosedPipe
		}
		//可以读数据了
		if p.data != nil {
			break
		}
		 //writer关闭了
		if p.werr != nil {
			return 0, p.werr
		}
		//阻塞读
		p.rwait.Wait()
	}
	//读数据
	n = copy(b, p.data)
	p.data = p.data[n:]
	//pipe中数据读完了则可以notify Writer
	if len(p.data) == 0 {
		p.data = nil
		p.wwait.Signal()
	}
	return
}

func (p *pipe) write(b []byte) (n int, err error) {
	// pipe uses nil to mean not available
	if b == nil {
		b = zero[:]
	}

	// One writer at a time.
	p.wl.Lock()
	defer p.wl.Unlock()

	p.l.Lock()
	defer p.l.Unlock()
	//Writer关闭抛异常
	if p.werr != nil {
		err = ErrClosedPipe
		return
	}
	//写入数据
	p.data = b
	//notify Reader
	p.rwait.Signal()
	//阻塞,直到Reader读完
	for {
		if p.data == nil {
			break
		}
		if p.rerr != nil {
			err = p.rerr
			break
		}
		if p.werr != nil {
			err = ErrClosedPipe
			break
		}
		p.wwait.Wait()
	}
	n = len(b) - len(p.data)
	p.data = nil // in case of rerr or werr
	return
}


PipeReader/PipeWriter

定义

通过Pipe()函数创建(*PipeReader, *PipeWriter)

type PipeReader struct {
	p *pipe
}
type PipeWriter struct {
	p *pipe
}

方法

  • Write,调用pipe.write
  • Read,调用pipe.read
原文地址:https://www.cnblogs.com/suolu/p/6731184.html