英文:
go error on doing HTTP requests
问题
当运行以下HTTP客户端对Web服务器进行压力测试时,出现了奇怪的错误,想知道是什么原因。Go的版本是go1.8.1 linux/amd64
,运行在Ubuntu 14.04上,内存为16GB。
以下是代码运行时的输出:
$ go run te2.go
563.904492ms
Get http://10.3.0.6/small: dial tcp 10.3.0.6:80: connect: cannot assign requested address
Get http://10.3.0.6/small: dial tcp 10.3.0.6:80: connect: cannot assign requested address
Get http://10.3.0.6/small: dial tcp 10.3.0.6:80: connect: cannot assign requested address
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x5e3b27]
goroutine 140284 [running]:
main.httpGet(0x0)
/home/jon/learn/go/te2.go:27 +0x107
created by main.main
/home/jon/learn/go/te2.go:45 +0xd3
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x5e3b27]
goroutine 140375 [running]:
main.httpGet(0x0)
/home/jon/learn/go/te2.go:27 +0x107
created by main.main
/home/jon/learn/go/te2.go:45 +0xd3
exit status 2
有什么想法吗?
以下是代码片段:
package main
import "fmt"
import "bufio"
import "os"
import "time"
import "net/http"
var req = []byte("GET /small HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Length: 0\r\n\r\n")
var buf = make([]byte, 1024)
var total = 0
var t0 = time.Now()
var c = make(chan int)
func httpGet() int {
req, err := http.NewRequest("GET", "http://10.3.0.6/small", nil)
//req.Header.Add("User-Agent", `MYCLIENT`)
//req.Header.Add("Cookie", `sessid=12345`)
client := &http.Client{}
resp, err := client.Do(req)
//defer resp.Body.Close()
if err != nil {
fmt.Println(err)
}
resp.Body.Close()
total++
if total == 10000 {
fmt.Println(time.Now().Sub(t0))
}
c <- 1
return 0
}
func main() {
i := 1
t0 = time.Now()
for i < 1000 {
go httpGet()
i += 1
}
for 1 < 2 {
<-c
go httpGet()
}
reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n')
fmt.Println(text)
}
英文:
When running the following http client to stress test a web server, got strange error, wonder what was the cause. The version of go is go1.8.1 linux/amd64
running on Ubuntu 14.04 with 16GB of ram.
$ go run te2.go
563.904492ms
Get http://10.3.0.6/small: dial tcp 10.3.0.6:80: connect: cannot assign requested address
Get http://10.3.0.6/small: dial tcp 10.3.0.6:80: connect: cannot assign requested address
Get http://10.3.0.6/small: dial tcp 10.3.0.6:80: connect: cannot assign requested address
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x5e3b27]
goroutine 140284 [running]:
main.httpGet(0x0)
/home/jon/learn/go/te2.go:27 +0x107
created by main.main
/home/jon/learn/go/te2.go:45 +0xd3
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x5e3b27]
goroutine 140375 [running]:
main.httpGet(0x0)
/home/jon/learn/go/te2.go:27 +0x107
created by main.main
/home/jon/learn/go/te2.go:45 +0xd3
exit status 2
any ideas?
Here is the code snippet:
package main
import "fmt"
import "bufio"
import "os"
import "time"
import "net/http"
var req = []byte("GET /small HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Length: 0\r\n\r\n");
var buf = make([]byte, 1024)
var total = 0;
var t0 = time.Now()
var c = make(chan int)
func httpGet () int {
req, err := http.NewRequest("GET", "http://10.3.0.6/small", nil)
//req.Header.Add("User-Agent", `MYCLIENT`)
//req.Header.Add("Cookie", `sessid=12345`)
client := &http.Client{}
resp, err := client.Do(req)
//defer resp.Body.Close()
if (err != nil) {
fmt.Println(err)
}
resp.Body.Close()
total ++
if (total == 10000) {
fmt.Println(time.Now().Sub(t0))
}
c <- 1
return 0;
}
func main() {
i := 1
t0 = time.Now()
for (i < 1000) {
go httpGet()
i += 1
}
for (1 < 2) {
<-c
go httpGet()
}
reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n')
fmt.Println(text)
}
答案1
得分: 3
在这个片段中,你正在检查err
并继续执行。
所以如果发生了某些事情,err
不是nil
,但resp
(或resp.Body
)是nil
指针-你会打印错误然后解引用一个空指针。
你应该这样做:如果发生错误-清理并从函数中返回。
英文:
resp, err := client.Do(req)
//defer resp.Body.Close()
if (err != nil) {
fmt.Println(err)
}
resp.Body.Close()
In this fragment you're checking the err
and continue execution.
So if something happened and the err
is not nil
, but resp
is (or the resp.Body
is) - you print the error then dereference a nil pointer.
What you should have done: if an error occurs - cleanup and return from the function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论