//比如要解析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大小那里的逻辑,确实有点绕。。。。。。