This is the 15th day of my participation in the Gwen Challenge.More article challenges
Code encapsulation can be a chore, but sometimes encapsulation can cause problems. This article documented a problem with nil determination that individuals encountered when encapsulating HTTP requests.
What is nil
Nil A built-in variable that represents null values, and only Pointers, channels, methods, interfaces, maps, and slices can be assigned nil.
Buildin/buildin. Go:
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
// Type is here for the purposes of documentation only. It is a stand-in
// for any Go type, but represents the same type for any given function
// invocation.
type Type int
Copy the code
The problem code
The following code is my wrapper around the HTTP. Post method
func (r *Request) Post(endpoint string, params *url.Values, body io.Reader, headers map[string]string, cookies map[string]string) (resp *http.Response, err error) {
url := fmt.Sprintf("%s%s", r.BaseURL, endpoint)
var req *http.Request
req, err = http.NewRequest(http.MethodPost, url, body)
iferr ! =nil {
return
}
r.setRequest(req, params, headers, cookies)
resp, err = r.Client.Do(req)
return
}
Copy the code
Then use it like this:
var body *bytes.Reader
body = nil
resp, err = req.Post(endpoint, nil, body, nil.nil)
Copy the code
NewRequest (http.newRequest, http.newRequest, http.newRequest, http.newRequest)
Error analysis
The underlying implementation of Pointers and interfaces has two parts: Data and Type. When Pointers and interfaces are explicitly assigned nil, both data and type are nil, but when a value of type not nil but data is nil is assigned to a pointer or interface, the comparison to nil results in false.
Modify the code
Use reflect.valueof (body).isnil () to determine if the body is empty:
func (r *Request) Post(endpoint string, params *url.Values, body io.Reader, headers map[string]string, cookies map[string]string) (resp *http.Response, err error) {
url := fmt.Sprintf("%s%s", r.BaseURL, endpoint)
var req *http.Request
if reflect.ValueOf(body).IsNil() {
req, err = http.NewRequest(http.MethodPost, url, nil)}else {
req, err = http.NewRequest(http.MethodPost, url, body)
}
iferr ! =nil {
return
}
r.setRequest(req, params, headers, cookies)
resp, err = r.Client.Do(req)
return
}
Copy the code