英文:
Segmentation violation with golang channels
问题
以下代码打开了10,000个goroutine,它们进行HTTP调用,获取响应,关闭响应,并将响应写入带有ID的通道。
在第二个for循环中,它从缓冲通道中打印出前一个goroutine的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)
}
}
英文:
The below code opens 10,000 go routines, which make HTTP calls, get the response, close the response, and write to a channel with an ID.
In the second for loop, it prints out from that buffered channel the ID of the previous go routine.
This causes a segmentation violation, and I can't figure out why.
Panic:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x2293]
Code:
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)
}
}
答案1
得分: 6
你在调用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)
}
}
希望对你有帮助!
英文:
You do not check for any error when calling the api. Thus the error when trying to close a response that never arrived.
This code does not panic:
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)
}
}
答案2
得分: 2
这个错误的一般原因是当你尝试引用一个不存在或尚未创建的对象时。在上面的代码中,如果你在body
不存在时尝试调用resp.Body.Close()
,就会出现空指针引用的错误。
英文:
The general cause of this error is when you try to reference an object that does not exist or has not yet been created.
In the code above, if you try to call resp.Body.Close()
when body
does not exist, that becomes a nil pointer reference and hence the error.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论