這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
//比如要解析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 Runebootstrap [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 // 0if b.off >= len(b.buf) { b.Truncate(0) //還沒有寫就想讀,清空buf}for {if free := cap(b.buf) - len(b.buf); free < MinRead {// free的大小是總容量 - 現在佔有長度newBuf := b.bufif b.off+free < MinRead { //分配更大空間,分配失敗會報錯newBuf = makeSlice(2*cap(b.buf) + MinRead)}//把讀的內容b.buf[b.off:]拷貝到newbuf前面去copy(newBuf, b.buf[b.off:])//讀寫之間的差距就是應該讀的bufb.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 = opInvalidif 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 += nif n > 0 {b.lastRead = opRead}return}
總之,這裡分析比較少腦筋的代碼就是那個ReadFrom裡面修改buf大小那裡的邏輯,確實有點繞。。。。。。