• 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
  • 相关阅读:
    Microsoft Artificial Intelligence Conference(2018.05.21)
    Insider Dev Tour(2018.06.28)
    AWS re:Invent(2019.01.09)
    OPPO Developers Conference(2018.12.26)
    Tencent Cloud Developers Conference(2018.12.15)
    China Intelligent Office Summit(2018.11.21)
    International Programming Retreat Day(2018.11.17)
    Intel Artificial Intelligence Conference(2018.11.14)
    OSC Source Code Innovation Salon(2018.10.20)
    Java CAS 比较并且更换值
  • 原文地址:https://www.cnblogs.com/suolu/p/6731184.html
Copyright © 2020-2023  润新知