在进行HTTP请求时出现了错误。

huangapple go评论96阅读模式
英文:

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 &quot;fmt&quot;
import &quot;bufio&quot;
import &quot;os&quot;
import &quot;time&quot;
import &quot;net/http&quot;

var req = []byte(&quot;GET /small HTTP/1.1\r\n&quot; +
&quot;Host: localhost\r\n&quot; +
&quot;Content-Length: 0\r\n\r\n&quot;);
var buf = make([]byte, 1024)
var total = 0;
var t0 = time.Now()
var c = make(chan int)

func httpGet ()  int {
	req, err := http.NewRequest(&quot;GET&quot;, &quot;http://10.3.0.6/small&quot;, nil)
	//req.Header.Add(&quot;User-Agent&quot;, `MYCLIENT`)
	//req.Header.Add(&quot;Cookie&quot;, `sessid=12345`)
	client := &amp;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 &lt;- 1
	return 0;
}

func main() {
	i := 1
	t0 = time.Now()
	for (i &lt; 1000) {
		go httpGet()
		i += 1
	}
	for (1 &lt; 2) {
		&lt;-c
		go httpGet()
	}
	reader := bufio.NewReader(os.Stdin)
	text, _ := reader.ReadString(&#39;\n&#39;)
    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.

huangapple
  • 本文由 发表于 2017年5月8日 11:03:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/43839145.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定