问题场景

准备在读取一个网络地址,获取页面的html标签结构和内容。找到一些方法,是通过读取 http.Get(testUrl)返回的HTTP response body resp *Response 的内容resp.Body再使用net/html库进行读取分析。第一次获取title 标签,第二次获取某个a 标签,但是第二次无法读到资源。

猜测

猜测指针在遍历时指向了结束,或许在一次读写后关闭了资源。需要再次进行打开读取? 通过复制的方式多搞几个再操作?

搜索 #Read Twice resp *Response # Body io.ReadCloser

得到的是继续向下追踪源代码进行思考。 实际上要追根溯源 resp.Body 的Body 是Body io.ReadCloser 而ReadCloser是一个接口

// ReadCloser is the interface that groups the basic Read and Close methods.
type ReadCloser interface {
    Reader
    Closer
}

这只得到了部分一个部分的解释,但是并没有给出为什么会造成只能读取一次的原理。

解决

通过"io/ioutil” 读取后创建多个副本来进行读取。 ioutil.ReadAll 返回 []byte 之后使用bytes.NewReader(b) 创建一个新的 *Reader 这种思想似乎印证的之前的猜测直接进行复制,但是为什么要使用ReadAll呢?

    func main(){
            resp, err := http.Get(testUrl)
            if err != nil {
                fmt.Println("errr--------")
            }
            defer resp.Body.Close()

            b, err := ioutil.ReadAll(resp.Body)
            //读取
            if err !=nil{
                panic(err)
            }
            //创建一个
            reader := bytes.NewReader(b)
            //创建第二个
            readerTitle := bytes.NewReader(b)
            videoSrc  = alink.href(reader)
            title = alink.Title(readerTitle)
            ...
            }