我的代码可以完美运行,直到我想使用许多并发调用对其进行扩展。 通过询问客户一个Get请求来工作。

这就是我得到的:

1
2
3
4
5
6
7
8
9
10
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x400da9]

goroutine 125 [running]:
runtime.panic(0x697480, 0x850d13)
    /usr/lib/go/src/pkg/runtime/panic.c:279 +0xf5
main.concurrent(0x25e5)
    /home/maker/go/src/GoBot/GoBot.go:19 +0x1a9
created by main.main
    /home/maker/go/src/GoBot/GoBot.go:51 +0x224

我认为我没有正确处理错误,并且在发出很多请求时会崩溃。

1
2
3
4
5
6
7
8
9
10
func concurrent(n uint64) {
    for i := n; i < n+11; i++ {
            member,  err := s.GetUser(i)
            output <- fmt.Sprint(member.Username) //This is line 19 that triggers the error
            if err != nil && member != nil {
              continue
           }
     }
defer wg.Done()
}

我该如何解决?
s.GetUser的参考在这里:
https://github.com/njasm/gosoundcloud/blob/master/soundcloud.go#L274

  • 即使在GetUser返回错误的情况下,您也在第19行使用member。 它似乎与并发无关-也许您现在看到它是因为并发版本对GetUser进行了更多调用。

首先,可以通过检查当前忽略的返回值GetUser来防止出现恐慌;

1
2
3
4
5
6
7
8
9
10
        member,  err := s.GetUser(i)
        if err != nil {
           // handle error
        }
        if member != nil { // prevents the panic attempting to access Username on nil instance of user/member
             output <- fmt.Sprint(member.Username) //This is line 19 that triggers the error
            if err != nil && member != nil {
              continue
           }
       }

除此之外,GetUser在做什么? 如果正在执行HTTP GET,则通常应用程序将阻塞直到返回,这意味着,如果您检查错误,则可能会出现HTTP 404、403、500等错误。

如果对GetUser的调用是并发的,那么您可能会遇到一个问题,其中下面的代码在GetUser返回导致nil恐慌之前尝试访问member.Username,但是我不知道怎么回事 因为那里没有goroutine。 它应该只是一个简单的阻塞调用。 如果您发现上述建议并未导致问题的根本原因,请使用GetUser的结果及其实现来编辑您的问题,我将对其进行进一步研究。

  • 实际上,我将函数变成了goroutines。 有没有更好的方法可以做到这一点,或者仅通过检查即可解决问题? @evanmcdonnal
  • @Juanvulcano我假设您在像go concurrent(10)这样的go例程中调用concurrent,您在concurrent中没有goroutine,因此在该范围内没有并发性。 话虽如此,只是检查可能会为您完成,如果根本原因不是GetUser中的失败,我会感到惊讶
  • 我正在使用for循环。 play.golang.org/p/WyjoLFzCVW我做错了吗? @evanmcdonnal
  • 我实现了您的代码,但仍然失败。 会是什么呢?