Memory goroutines内存不足UPD:go错误处理

Memory goroutines内存不足UPD:go错误处理,memory,go,goroutine,Memory,Go,Goroutine,UPD:事实证明,这是一个关于Go中错误处理的问题 我编写了一个简单的网络爬虫程序,它在“主线程”上生成网页地址,在一个go例程中获取实际页面,并通过chan返回内容,然后在另一个go例程中将其写入文件。但是,经过大约300000次迭代后,我得到以下错误: panic: runtime error: invalid memory address or nil pointer dereference [signal 0xb code=0x1 addr=0x38 pc=0x22e9]</pre

UPD:事实证明,这是一个关于Go中错误处理的问题

我编写了一个简单的网络爬虫程序,它在“主线程”上生成网页地址,在一个go例程中获取实际页面,并通过
chan
返回内容,然后在另一个go例程中将其写入文件。但是,经过大约300000次迭代后,我得到以下错误:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x38 pc=0x22e9]</pre>
panic:运行时错误:无效内存地址或零指针取消引用
[信号0xb代码=0x1地址=0x38 pc=0x22e9]
“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 {
    ...
}
主程序包
进口(
“fmt”
“io/ioutil”
“net/http”
“strconv”
)
func main(){
通道:=make(通道[]字节)
对于i:=0;i<20;i++{
go抓取器(generateLink(),通道)
}
对于a:=0;;a++{
去写文件(strconv.Itoa(a),
这意味着您试图使用nil指针。这是一个程序员错误,而不是内存不足错误。由于我无法访问实际跟踪或代码,因此我无法进一步帮助您


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

resp, err := http.Get(url)
if err != nil {
    channel <- []byte("")
}
defer resp.Body.Close()
响应,错误:=http.Get(url) 如果错误!=零{ 频道 这意味着您试图使用nil指针。这是一个程序员错误,而不是内存不足错误。由于我无法访问实际跟踪或代码,因此我无法进一步帮助您


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

resp, err := http.Get(url)
if err != nil {
    channel <- []byte("")
}
defer resp.Body.Close()
响应,错误:=http.Get(url) 如果错误!=零{
通道我在这里只是猜测,因为我没有stacktrace。但以下两行对我来说是可疑的:

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

通道我在这里只是猜测,因为我没有stacktrace。但以下两行对我来说是可疑的:

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

通道在某一点上,对
http.Get()
的调用失败,并返回一个非nil的
err
。当这种情况发生时,您将一个空字节片放入通道中,但您继续运行,并在
resp
为nil时尝试从
resp.Body
读取数据。

在某一点上,您对
http.Get()的调用
失败并返回一个非零的
错误
。当这种情况发生时,您将一个空字节片放入通道,但您继续,并尝试从
resp.Body
读取。无论如何,当
resp
为零时。

谢谢您的回复。代码非常实际,唯一省略的是链接生成。我如何知道我的e在哪里错误是由跟踪判断的?粘贴恐慌或转到IRC通道。回溯应列出导致恐慌的确切行。精确。OP需要在通道上放置空字节片后返回。是的,非常感谢大家。我在实际再次捕获异常时发现了同样的情况。感谢您的回复。代码是预处理的tty实际,唯一被忽略的是链接生成。我如何根据跟踪判断我的错误在哪里?粘贴死机或转到IRC通道。回溯应该列出导致死机的确切行。完全正确。OP需要在通道上放置空字节片后返回。是的,非常感谢。我发现了同样的事情当我再次捕捉到异常时。因为body不是指针,所以它不能被引用并导致这种类型的恐慌。最坏的情况是你得到一个空的nil片。因为body不是指针,所以它不能被引用并导致这种类型的恐慌。最坏的情况是你得到一个空的nil片。假设你启动了
godoc
put
return”http://localhost:8080“
作为
generateLink()
的主体。您仍然会失败吗?假设您启动
godoc
put
return”http://localhost:8080“
作为
generateLink()
的主体。您仍然得到失败吗?