使用gorutine(golang)的内存地址无效

时间:2017-05-17 14:59:38

标签: go xml-parsing request buffer goroutine

我正在使用的代码仅在我将其作为阻止例程运行时才有效...但如果我使用go executeTheFunction,我总是得到panic: runtime error: invalid memory address or nil pointer dereference。总结一下这个代码就像那样。

func (c App) Index() revel.Result {
    app = c; //this is a "global" variable to be used in callBackFunction 
    options = "foo";
    client  = NewClient()
    client.RequestAsynch(options, callBackFunction);
}
func callBackFunction(message string){
    reader := bytes.NewBufferString(message)
    _, err := xmlpath.Parse( reader )
    if err != nil {
        panic(err)
    }
    flusher, ok := airshopping.Response.Out.(http.Flusher)
    if !ok {
      panic("expected http.ResponseWriter to be an http.Flusher")
    }

    fmt.Fprintf(airshopping.Response.Out, "whatever")
    flusher.Flush()
}

func (client * Client)RequestAsynch(message Message, callback func(string)) {
    Response := client.Request(message)

    message_aux := ""
    reader := bufio.NewReader(Response.Body)
    for {
        line, err := reader.ReadBytes('\n')
        if err==nil {
            message_aux = message_aux + string(line)
            if strings.Contains(message_aux, "<!-- AG-EOM -->"){
                go callback(message_aux)
                message_aux = ""
            }
        }else{fmt.Println("ERROR", err);break;}
    }
}

好的......我要解释一下。 RequestAsynch位于不同的包中,它向其他服务器发送请求。这个其他服务器响应多个xml ...这些xml的主体看起来像:

<!-- Header status:ok -->
<all_the_xml_response>
<!-- AG-EOM -->

所以...当逐行循环检测到这个"<!-- AG-EOM -->"时,其中一个xml被完全接收,并且应该执行callBack函数(使用gorutine)。这个callBack函数的任务是解析xml,并在解析过程之后,将一些数据发送回客户端的javascript。

我一直得到的错误是:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x20 pc=0x4f8c09]

goroutine 80 [running]:
bufio.(*Writer).Write(0xc042454540, 0xc0422d4000, 0x11076, 0x12000, 0xc04202fb30, 0x4683b7, 0x11076)
    C:/Go/src/bufio/bufio.go:598 +0x149
net/http.(*response).write(0xc04234d0a0, 0x11076, 0xc0422d4000, 0x11076, 0x12000, 0x0, 0x0, 0xc0422d4000, 0x0, 0x0)
    C:/Go/src/net/http/server.go:1525 +0x157
net/http.(*response).Write(0xc04234d0a0, 0xc0422d4000, 0x11076, 0x12000, 0x0, 0x0, 0xc042824000)
    C:/Go/src/net/http/server.go:1495 +0x6b
fmt.Fprintf(0xb65e80, 0xc04234d0a0, 0xc042824000, 0x11076, 0x0, 0x0, 0x0, 0xc0421445f0, 0xb, 0xc0422f5e00)
    C:/Go/src/fmt/print.go:182 +0xb0
ndc-console-test/app/controllers/ndcmethods.GetOffers_AS(0xc042594000, 0xef7f)
    F:/Proyectos_Trabajo/work/src/ndc-console-    test/app/controllers/ndcmethods/airshopping.go:98 +0x7a1
created by github.com/open-ndc/ndc-go-sdk.(*Client).RequestAsynch
    F:/Proyectos_Trabajo/work/src/github.com/open-ndc/ndc-go-sdk/ndc_client.go:143 +0x25c
2017/05/17 16:42:56 reverseproxy.go:316: http: proxy error: dial tcp [::1]:55058: connectex:A connection can not be established because the target computer expressly denied the connection.

在此错误之后......我需要重新启动服务器,因为它不允许建立新连接。

我看到的一件事是,如果我在callBackFunction中删除此行_, err := xmlpath.Parse( reader ),它可以正常工作。当然,如果我改变这一行:go callback(message_aux) callback(message_aux)(没有goroutine)它也可以正常工作,并且解析xml没有问题。

有没有人知道如何使用goroutines避免此错误的解决方案??

非常感谢。

修改

我认为我没有很好地表达其他服务器如何响应,这就是(多个)响应的看法:

<!-- Header status:ok -->
<the_xml_response_of_one_response_or_one_chunk>
<!-- AG-EOM -->
<!-- Header status:ok -->
<other_xml_response>
<!-- AG-EOM -->
<!-- Header status:ok -->
<other_more_xml_response>
<!-- AG-EOM -->

1 个答案:

答案 0 :(得分:0)

根据您的堆栈跟踪,似乎问题是一旦父函数返回就会写出HTTP响应,到新goroutine有机会尝试时,编写器不再可用。< / p>

这是net/http设计的一部分,因此我怀疑您的RequestAsynch无法按照预期编写。为什么需要异步?每个请求都已在自己的goroutine中处理。

BTW,strings.NewReader可能比bytes.NewBufferString更合适,因为您不需要完整的缓冲区接口。