doujuncuo9339 2016-05-27 01:11
浏览 134
已采纳

去Reader.read(); 如何获得内容而不重复?

I've started studying Go recently as a side project and have been trying to get a better handle around the Reader interface. Specifically, I'm trying to get contents from a website, and then reading it to a bytes slice.

I am aware that the ioutils.ReadAll function is the canonical way to get the data, but I'm curious why the original function I wrote has repeated content at the end of the output.

Code: package main

import(
    "net/http"
    "fmt"
)

func main() {
    // retrieve url from hacker news.
    resp, err := http.Get("http://news.ycombinator.com/")
    if err != nil {
        // handle error
    }
    defer resp.Body.Close()
    text := make([]byte, 500)
    buf := make([]byte, 200)
    i, _ := resp.Body.Read(buf)
    for i != 0 {
        text = append(text,buf...)
        i, _ = resp.Body.Read(buf)
    }
    fmt.Println(resp.ContentLength)
    fmt.Println(resp.Status)
    fmt.Printf("%q
", text)

}

Content:

         (...)Search:
  <input type=\"text\" name=\"q\" value=\"\" size=\"17\" autocorrect=\"off\" spellcheck=\"false\" autocapitalize=\"off\" autocomplete=\"false\"></form>
            </center></td></tr>      
         </table></center></body></html>
put type=\"text\" name=\"q\" value=\"\" "

As you can see, for a reason I don't quite understand, one part of the text is repeated at the end after the closed tags; 'nput type=\"text\" name=\"q\" value=\"\" "'.

Maybe this is something related to the buffer not being cleared maybe? Could anyone offer some insight as to what I am getting wrong?

  • 写回答

1条回答 默认 最新

  • 普通网友 2016-05-27 01:25
    关注

    The io.Reader interface returns the number of bytes read and an error value. You need to make use of both values.

    The int return value shows tells you how many bytes have been read into your the buffer, and error informs you of error conditions as well as when you've reached EOF. A Reader may also return bytes read and an io.EOF on the same call, so you should handle that as well.

    Also note that you create a slice for text of 500 bytes, but then you append to it, leaving 500 null characters at the beginning.

    var text []byte
    buf := make([]byte, 256)
    
    var n int
    var err error
    
    for err == nil {
        n, err = resp.Body.Read(buf)
        text = append(text, buf[:n]...)
    }
    
    if err != io.EOF {
        log.Fatal("error:", err)
    }
    

    (Unrelated to Go, blocks of memory tend to work most efficiently when they are aligned to powers of 2.)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?