使用golang频道进行分段违规

时间:2017-01-25 18:10:17

标签: go channel

以下代码打开10,000个例程,这些例程进行HTTP调用,获取响应,关闭响应,并写入具有ID的通道。

在第二个for循环中,它从该缓冲的通道打印出前一个例程的ID。

这导致分段违规,我无法弄清楚原因。

恐慌:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x2293]

代码:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    requests := 10000
    ch := make(chan string, requests)
    for i := 1; i <= requests; i++ {
        go func(iter int) {
            fmt.Println(iter)
            resp, _ := http.Get("http://localhost:8080/api/project")
            resp.Body.Close()
            ch <- fmt.Sprint("%i", iter)
        }(i)
    }
    for i := 1; i <= requests; i++ {
        fmt.Println(<-ch)
    }
}

2 个答案:

答案 0 :(得分:3)

调用api时不会检查是否有任何错误。因此,当尝试关闭从未到达的响应时出现错误。

此代码并不恐慌:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    requests := 10000
    ch := make(chan string, requests)
    for i := 1; i <= requests; i++ {
        go func(iter int) {
            fmt.Println(iter)
            resp, err := http.Get("http://localhost:8080/api/project")
            if (err == nil) {
              resp.Body.Close()
            }
            ch <- fmt.Sprint(iter)
        }(i)
    }
    for i := 1; i <= requests; i++ {
        fmt.Println(<-ch)
    }
}

答案 1 :(得分:0)

此错误的一般原因是当您尝试引用不存在或尚未创建的对象时。

在上面的代码中,如果您在 resp.Body.Close() 不存在的情况下尝试调用 body,则会变成 nil 指针引用,从而导致错误。