golang把io.ReadCloser類型轉化為[]byte

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
//比如要解析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大小那裡的邏輯,確實有點繞。。。。。。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.