0

UPD:原来,这是一个关于 Go 中的错误处理的问题

我编写了一个简单的网络爬虫,它在“主线程”上生成网页的地址,在一个 go-routine 中获取实际页面并通过 a 返回内容chan,并将其写入另一个 go-常规。但是,经过大约 300,000 次此过程的迭代,我收到以下错误:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x38 pc=0x22e9]</pre>

错误“stacktrace”很长,不幸的是,我现在没有它(我会在重复实验后发布它)。

是否需要以某种方式管理内存、关闭通道或类似的东西?

下面是有一些遗漏的代码。

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "strconv"
)

func main() {
    channel := make(chan []byte)

    for i:=0; i < 20; i++ {
        go fetcher(generateLink(), channel)
    }

    for a:=0; ; a++ {
        go writeToFile(strconv.Itoa(a), <-channel)
        go fetcher(generateLink(), channel)
        fmt.Println(strconv.Itoa(a))
    }
}

func fetcher(url string, channel chan []byte) {

    resp, err := http.Get(url)
    if err != nil {
        channel <- []byte("")
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    channel <- body
}

func writeToFile(filename string, bytes []byte) {
    ioutil.WriteFile(filename+".html", bytes, 0644)
}

func generateLink() string {
    ...
}
4

3 回答 3

3
panic: runtime error: invalid memory address or nil pointer deference

这意味着您尝试使用 nil 指针。这是程序员错误,而不是内存不足错误。由于我无法访问实际的跟踪或代码,因此我无法进一步帮助您。


编辑:再次查看您的代码后,我想我找到了可能的错误来源。

resp, err := http.Get(url)
if err != nil {
    channel <- []byte("")
}
defer resp.Body.Close()

即使. _ resp_ 如果,则很可能 resp 为零。Bodyerr != nilerr !=nil

于 2012-08-17T20:29:26.320 回答
1

我只是在这里猜测,因为我没有堆栈跟踪。但以下两行对我来说看起来很可疑:

body, err := ioutil.ReadAll(resp.Body)
channel <- body

当你在频道上发送它时,你怎么知道身体不是零?由于 writeToFile 也没有检查它,因此您完全有可能尝试将 nil 字节切片写入文件并且它在那里爆炸。如果您发现错误,您应该在继续之前检查它。

于 2012-08-17T20:41:29.537 回答
1

在某些时候,您的调用http.Get()失败并返回一个非 nil err。发生这种情况时,您将一个空字节切片放入通道中,但您继续前进,并尝试从任何情况下读取resp.Body,何时resp为 nil。

于 2012-08-17T20:54:37.863 回答