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

时间:2016-05-27 01:11:14

标签: html web go buffer

我最近开始学习Go作为一个侧面项目,并一直试图更好地处理Reader界面。具体来说,我正在尝试从网站获取内容,然后将其读取到字节切片。

我知道ioutils.ReadAll函数是获取数据的规范方法,但我很好奇为什么我写的原始函数在输出结束时重复了内容。

代码:     包主要

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\n", text)

}

内容:

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

正如你所看到的,由于一个我不太了解的原因,文本的一部分在封闭的标签之后重复; 'nput type = \“text \”name = \“q \”value = \“\”“'。

也许这是与缓冲区有关的东西可能没有被清除?任何人都可以提供一些关于我出错的见解吗?

1 个答案:

答案 0 :(得分:2)

io.Reader接口返回读取的字节数和错误值。您需要使用这两个值。

int返回值显示告诉您已经读入缓冲区的字节数,并且错误会通知您错误情况以及何时达到EOF。 Reader也可以在同一个调用中返回字节读取和io.EOF,因此您也应该处理它。

另请注意,您为500个字节的text创建了一个切片,但随后附加到它,在开头留下500个空字符。

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)
}

(与Go无关,当它们与2的幂对齐时,内存块往往效率最高。)