我最近开始学习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 = \“\”“'。
也许这是与缓冲区有关的东西可能没有被清除?任何人都可以提供一些关于我出错的见解吗?
答案 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的幂对齐时,内存块往往效率最高。)