DjanFey的基础库解读--io包(multi.go)

DjanFy · · 604 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

package my_io

type eofReader struct {

}

func (eofReader) Read([]byte) (int, error) {
   return 0,EOF
}

type multiReader struct {
   readers []Reader
}

func (mr *multiReader) Read(p []byte) (n int, err error) {
   for len(mr.readers)>0{
      // 对展开嵌套multiReaders的优化(Issue 13558)
      // 如果readers只有一个元素且也是multiReader类型的,直接将元素的readers赋值给最外层的readers
      if len(mr.readers)==1{
         if r,ok:=mr.readers[0].(*multiReader);ok{
            mr.readers=r.readers
            continue
         }
      }
      // 每次从切片中读取第一个Reader的数据
      n,err=mr.readers[0].Read(p)
      if err==EOF{
         // 在改善展开嵌套的问题(Issue 18232)后用eofReader代替nil来避免nil报错
         mr.readers[0]=eofReader{}
         // 将readers收缩以排除已经读取完的reader
         mr.readers=mr.readers[1:]
      }
      // 它们会被顺序读取。一旦所有的Reader都返回EOF,那么Read
      if n>0 || err!=EOF{
         if err==EOF&&len(mr.readers)>0{
            // 先不要返回EOF,因为readers中还保留有Reader
            err=nil
         }
         return
      }
   }
   // 所有Reader的数据都读取完了
   return 0,EOF
}

// MultiReader返回一个Reader, 那是提供的readers的逻辑上的串联,
// 它们会被顺序读取。一旦所有的输入都返回EOF,那么Read就会返回EOF。
// 如果readers的任何一个Reader返回一个非空,非EOF的错误,那么Read会返回那个错误
func MultiReader(readers ...Reader) Reader {
   r:=make([]Reader,len(readers))
   copy(r,readers)
   return &multiReader{
      r,
   }
}

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
      }
      if n!=len(p){
         err=ErrShortWrite
         return
      }
   }
   return len(p),err
}

// 利用编译器检查*multiWriter是否实现了StringWriter接口,以及显示规定*multiWriter一定要实现StringWriter接口
var _ StringWriter = (*multiWriter)(nil)

func (t *multiWriter) WriteString(s string) (n int, err error) {
   var p []byte // 当需要的时候懒初始化
   for _,w:=range t.writers{
      if sw,ok:=w.(StringWriter);ok{
         n,err=sw.WriteString(s)
      }else {
         if p==nil{
            p=[]byte(s)
         }
         n,err=w.Write(p)
      }
      if err!=nil{
         return
      }
      if n!=len(s){
         err=ErrShortWrite
         return
      }
   }
   return len(s),nil
}

// MultiWriter创建一个writer,这个writer对每个提供的writer都进行重复的写操作
//
// 写操作会写入到每个writer,但一次只写一个
// 如果列出的writer有一个返回了一个错误,那么所有的写操作都会停止并且返回这个错误,不会继续按照列表执行下去。
func MultiWriter(writers ...Writer) Writer {
   allWriters:=make([]Writer,0,len(writers))
   for _,w:=range writers{
      if mw,ok:=w.(*multiWriter);ok{
         allWriters=append(allWriters,mw.writers...)
      }else {
         allWriters=append(allWriters,w)
      }
   }
   return &multiWriter{allWriters}
}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

604 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传