我遇到了与https://github.com/golang/go/issues/26666相同的问题,因为我的HTTP请求具有包装功能。
有时我需要请求:
body := new(bytes.Buffer)
json.NewEncoder(body).Encode(h)
req("POST", "http://example.com", body)
有时只是:
req("GET", "http://example.com", nil)
runtime error: invalid memory address or nil pointer dereference
我最终得到:
req("GET", "http://example.com", new(bytes.Buffer))
但是我不确定这是否正确。
功能:
func req(method string, url string, body *bytes.Buffer) int {
req, err := http.NewRequest(method, url, body)
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(user, psw)
resp, err := client.Do(req)
checkErr(err)
if resp.StatusCode > 500 {
time.Sleep(30 * time.Second)
resp, err = client.Do(req)
checkErr(err)
}
defer resp.Body.Close()
return resp.StatusCode
}
更新的功能:
func req(method string, url string, body io.Reader) int {
req, err := http.NewRequest(method, url, body)
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(user, psw)
resp, err := client.Do(req)
checkErr(err)
defer resp.Body.Close()
if resp.StatusCode >= 500 {
time.Sleep(30 * time.Second)
req, err := http.NewRequest(method, url, body)
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(user, psw)
resp, err := client.Do(req)
checkErr(err)
defer resp.Body.Close()
}
return resp.StatusCode
}
func checkErr(err error) {
if err != nil {
log.Fatal(err)
}
}
答案 0 :(得分:4)
http.NewRequest()
中的body
是可选的,因此在执行nil
请求时传递GET
是可以接受的。
问题是body
的{{1}}参数是接口类型:http.NewRequest
,并且您试图传递具体类型为io.Reader
的值。发生的情况是,该*bytes.Buffer
指针将被包装在非nil
接口值中,并将其作为主体传递给nil
。
如果您没有尸体,请像这样通过显式传递http.NewRequest
:
nil
然后您可以这样称呼它:
func req(method string, url string, body *bytes.Buffer) int {
var bodyToPass io.Reader
if body != nil {
bodyToPass = body
}
req, err := http.NewRequest(method, url, bodyToPass)
// ....
}
尽管最好的做法是,您的req("GET", "http://example.com", nil)
函数首先使用req()
,所以您不必显式检查其值:
io.Reader
您也可以使用func req(method string, url string, body io.Reader) int {
req, err := http.NewRequest(method, url, body) // You may pass it as-is
// ....
}
或非nil
nil
来调用它:
*bytes.Buffer
有关更多详细信息,请参见Hiding nil values, understanding why golang fails here