go把io.ReadCloser类型转化为[]byte

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 20:25   4089   0
//比如要解析resp.Body(io.ReadCloser),我们可以这样处理
body, err := ioutil.ReadAll(resp.Body)

接着,我们继续分析分析函数

func ReadAll(r io.Reader) ([]byte, error) {
 return readAll(r, bytes.MinRead) //const MinRead = 512
}
//
func readAll(r io.Reader, capacity int64) (b []byte, err error) {
 buf := bytes.NewBuffer(make([]byte, 0, capacity))
//func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} } 一个新的buffer实例

 defer func() {
  e := recover()
  if e == nil {
   return
  }
  //buf太大会返回相应错误
  if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
   err = panicErr
  } else {
   panic(e)
  }
 }()
 _, err = buf.ReadFrom(r) //关键就是这个家伙
 return buf.Bytes(), err
}

来继续看看 buf.ReadFrom的实现吧:

//先看一下Buffer的定义,有帮助下面理解
type Buffer struct {
 buf       []byte            // 最新数据存放在 buf[off : len(buf)]
 off       int               // 从&buf[off]开始读, 从&buf[len(buf)]开始写
 runeBytes [utf8.UTFMax]byte // avoid allocation of slice on each WriteByte or Rune
 bootstrap [64]byte          
 // memory to hold first slice; helps small buffers (Printf) avoid allocation.
 lastRead  readOp            // last read operation, so that Unread* can work correctly.
}


func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) {
 b.lastRead = opInvalid // 0
 if b.off >= len(b.buf) { 
  b.Truncate(0) //还没有写就想读,清空buf
 }
 for {
  if free := cap(b.buf) - len(b.buf); free < MinRead {
   // free的大小是总容量 - 现在占有长度
   newBuf := b.buf
   if b.off+free < MinRead {
                                //分配更大空间,分配失败会报错
    newBuf = makeSlice(2*cap(b.buf) + MinRead)
   }
   //把读的内容b.buf[b.off:]拷贝到newbuf前面去
   copy(newBuf, b.buf[b.off:])
   //读写之间的差距就是应该读的buf
   b.buf = newBuf[:len(b.buf)-b.off]
   b.off = 0
  }
  //把io.Reader内容写到buf的free中去
  m, e := r.Read(b.buf[len(b.buf):cap(b.buf)])
  //重新调整buf的大小
  b.buf = b.buf[0 : len(b.buf)+m]
  n += int64(m)
  //读到尾部就返回
  if e == io.EOF {
   break
  }
  if e != nil {
   return n, e
  }
 }
 return n, nil // err is EOF, so return nil explicitly
}

接下来再来看看是怎么Read进buf里面去的吧:

func (b *Buffer) Read(p []byte) (n int, err error) {
 b.lastRead = opInvalid
 if b.off >= len(b.buf) {
  // Buffer is empty, reset to recover space.
  b.Truncate(0)
  if len(p) == 0 {
   return
  }
  return 0, io.EOF
 }
 //就是这里咯,把b.buf[b.off:]的值写到p中去,记住copy(s1,s2)是s2写到s1中去,不要弄反咯
 //而且此Buffer其实是io.ReadCloser接口转化的类型
 n = copy(p, b.buf[b.off:])
 b.off += n
 if n > 0 {
  b.lastRead = opRead
 }
 return
}

总之,这里分析比较少脑筋的代码就是那个ReadFrom里面修改buf大小那里的逻辑,确实有点绕。。。。。。


转载于:https://my.oschina.net/yang1992/blog/502564

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP