This is a creation in Article, where the information may have evolved or changed.
For example, to parse resp. Body (IO. Readcloser), we can handle body like this, err: = Ioutil. ReadAll (resp. Body)
Next, we continue to analyze the analysis function
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}} A new Buffer instance def ER func () {e: = recover () If E = nil {return}//buf too assembly returns the corresponding error if panicerr, OK: = E. (error); OK && Panicerr = = BYTES.E Rrtoolarge {err = Panicerr} else {panic (e)}}} () _, err = buf. Readfrom (R)//The key is this guy return BUF. Bytes (), err}
Come on, look at BUF. Readfrom the realization of it:
First look at the definition of Buffer, which helps to understand Type buffer struct {buf []byte // latest data stored in &NBSP;BUF[OFF&NBSP;: len (BUF)]off int // from &buf[off] start reading, from &buf[len (BUF)] Start writing 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) //have not written to read, empty buf}for {if free := cap (B.BUF) - len (B.BUF); The size of free < minread {// free is the total capacity - now occupies length newbuf := b.bufif b.off+free < minread { //allocate more space, allocation failure will be error Newbuf = makeslice (2*cap (B.BUF) + minread)}//Read the content b.buf[b.off:] Copy to Newbuf front to copy (Newbuf, b.buf[b.off:])// The gap between reading and writing is what should be read Bufb.buf = newbuf[:len (b.buf)-b.off]b.off = 0}//the IO. The reader content is written to Buf's free M, e := r.read (B.buf[len (b.buf): Cap (B.BUF)])//resize buf b.buf = B.buf[0 : len (b.buf) +m]n += int64 (m)//read to the tail and return to If e == io. eof {break}if e != nil {return n, e}}return n, nil // err is eof, so return nil explicitly}
Let's take a look at how the read went into the BUF:
Func (b *buffer) Read (P []byte) (n int, err error) {b.lastread = Opinvalidif b.off >= len (b.buf) {//Buffer is empty, R ESET to recover space.b.truncate (0) If Len (p) = = 0 {return}return 0, Io. eof}//is here, the value of B.buf[b.off:] Write to the p, remember that copy (S1,S2) is S2 write to S1, do not reverse it//and this buffer is actually Io.readcloser interface conversion type n = Copy (P, b.buf [B.off:]) B.off + nif n > 0 {b.lastread = Opread}return}
In short, here the analysis of the less brain code is that readfrom inside modify BUF size there logic, really a bit around ...