【问题标题】:Figure source of "invalid memory address ... " with http.client带有http.client的“无效内存地址...”的图源
【发布时间】:2015-04-24 06:38:54
【问题描述】:

我正在学习并努力解决这个恐慌错误......它工作了一段时间,但很快就会出现这样的异常panic: runtime error: invalid memory address or nil pointer dereference

该函数简单地遍历代理映射,直到成功获取“地址”的内容。一定不是很地道,尤其是用map而不是slice和最后一个return,但我希望这不是恐慌粉碎的原因...... 如果我遗漏了一些可能很重要的内容,请告诉我,我会更新帖子,我只是不想用不必要的信息淹没它。 proxies 是一个带有 map 字段的结构,带有并发安全读取/删除的方法。

func getContent(address string) string {
localProxies := proxies.Get()
for proxy := range localProxies {
    proxyUrl, _ := url.Parse("http://" + proxy)

    transport := http.Transport{
        Dial:  dialTimeout,
        Proxy: http.ProxyURL(proxyUrl),
    }
    httpClient := http.Client{Transport: &transport, Timeout: timeout}
    req, err := http.NewRequest("GET", address, nil)
    if err != nil {
        fmt.Println("Request error: ", err.Error())
    }
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0")
    res, err := httpClient.Do(req)
    defer res.Body.Close()

    if err != nil {
        //          fmt.Println("Broken ", proxy)
        fmt.Println("Response error: ", err.Error())
        proxies.Del(proxy)
        continue
    }
    if res.StatusCode != 200 {
        //          fmt.Println("Status error: ", res.Status)
        proxies.Del(proxy)
        continue
    }
    out, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println("Read error: ", err.Error())
        proxies.Del(proxy)
        continue
    }
    return string(out)
}
return "error"

}

go version go1.4.2 linux/amd64

【问题讨论】:

  • 确切的错误信息是什么,包括行号,以及代码中对应的哪一行?
  • 可以肯定的是,您不应该检查if err != nil 您调用defer res.Body.Close()...之后应该首先检查错误。
  • 是否有必要发布所有堆栈,一开始它只是说panic: runtime error: invalid memory address or nil pointer dereference [signal 0xb code=0x1 addr=0x0 pc=0x408762] 然后它跟进了一长串其他信息..
  • 发布堆栈跟踪的开头。在顶部附近会有行号,但由于这可能与您发布的代码不匹配,我现在需要与该数字对应的行。

标签: go http.client


【解决方案1】:

在我看到更多信息之前,这只是基于我可以从您发布的代码中收集到的猜测。

电话

res.Body.Close()

应该在您检查错误之后,而不是之前。所以改变:

 res, err := httpClient.Do(req)
 defer res.Body.Close()
 if err != nil {
     ...
 }

 res, err := httpClient.Do(req)
 if err != nil {
     ...
 }
 defer res.Body.Close()

【讨论】:

  • 这么简单……我的脑子都快坏了,我做了几十个各种各样的东西,没想到defer肯定是在错误检查之后……非常感谢!
  • @MikeKlemin:没问题。快乐地鼠!
猜你喜欢
  • 2020-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-08
  • 2017-11-12
  • 1970-01-01
相关资源
最近更新 更多