HTTP
调用需要通过 http
包里的 Client
结构体里的 Do
方法去实现,因此需要先声明一个 Client
结构体变量,该结构体可以设置超时时间等配置。
对于一个请求里的 URL
,查询参数,请求 method
等参数,需要 http
包里的 Request
结构体去封装。我们可以通过 NewRequestWithContext
或 NewRequest
函数获取一个基础的 Request
结构体指针变量。
NewRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*Request, error)
- 参数
ctx
为Context
的接口类型,任意实现Context
接口的自定义类型都可以作为此参数传递。 - 参数
method
为HTTP
方法参数,可选值有GET
、POST
、DELETE
、PUT
等。 - 参数
url
为接口的请求路径。 - 参数
body
,为请求体参数。
通过 client.Do(req)
方法调用之后,返回值有 (*Response, error)
,第一个是响应结构体参数,第二个是错误参数。通过读取 Response
的 body
的值,可以获取接口的响应体。
一、GET
import ( "context" "fmt" "io" "net/http" ) func main() { client := http.Client{} request, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://localhost:8080/user?name=tom", nil) if err != nil { return } request.Header.Set("headerParam", "header") resp, err := client.Do(request) if err != nil { fmt.Println(err) return } bytes, err := io.ReadAll(resp.Body) if err != nil { return } defer resp.Body.Close() fmt.Println(string(bytes)) // {"code":0,"data":{"list":[{"name":"小明","age":20},{"name":"小红","age":18}]},"message":"success"} }
- 需要携带查询参数时,可以直接拼接在
url
字符串上面。 header
参数可以通过 request 结构体的Header
字段的set
方法或add
方法进行设置。- HTTP 请求响应码可以通过
Response
的StatusCode
字段进行查看。 - 接口请求成功之后,通过
io.ReadAll
方法,读取resp.Body
响应体信息。 - 除了直接在
url
上拼接query
参数的方式,我们还可以通过以下方式进行添加query
参数:
params := url.Values{} rawUrl, err := url.Parse("http://localhost:8080/user") if err != nil { return } params.Set("name", "tom") rawUrl.RawQuery = params.Encode() u := rawUrl.String()
通过 url.Values
结构体的 set
方法设置 query参数,url
通过 url.Parse
函数生成一个 URL
结构体指针变量,rawUrl.RawQuery = params.Encode()
通过这行代码将 query
参数和 url
进行绑定,最后通过 String()
方法将 url
转换成 string
类型。
二、POST
发起 HTTP
POST
请求时,携带 json
格式的 body
参数是最常见的,这是因为 json
格式的参数可读性好,对于层级结构较为复杂的数据也能应对,并且这符合 RestFul API
的规范。因此以下的示例为:发送 HTTP
POST
请求,并携带 json
类型的 body
参数。
import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" ) type User struct { Username string `json:"username"` Password string `json:"password"` } func main() { client := http.Client{} user := User{ Username: "123456", Password: "12346", } dataByte, err := json.Marshal(user) if err != nil { fmt.Println(err) } bodyReader := bytes.NewReader(dataByte) request, err := http.NewRequestWithContext(context.Background(), http.MethodPost, "http://localhost:8080/user", bodyReader) if err != nil { return } request.Header.Set("Content-Type", "application/json") resp, err := client.Do(request) if err != nil { fmt.Println(err) return } fmt.Println("statusCode: ", resp.StatusCode) body, err := io.ReadAll(resp.Body) if err != nil { return } defer resp.Body.Close() fmt.Println(string(body)) }
- 首先定义
User
结构体,创建结构体变量 user,通过json.Marshal
函数,将user
转成[]byte
数据,然后通过bytes.NewReader
函数,将[]byte
数据转成Reader
指针变量。 http.NewRequestWithContext
函数,最后一个参数是为body
参数,接收的变量类型是Reader
接口的实现体。第一步将user
转成Reader
指针变量就是为了在这里进行传递。- 传递
json
类型的body
参数,需要在请求头参数里设置Content-Type
的值为application/json
。
如果是发送 application/x-www-form-urlencoded
类型的表单数据,需要改写 body
参数的生成代码:
values := url.Values{} values.Set("username", "1234") values.Set("password", "1234") bodyReader := strings.NewReader(values.Encode())
本文通过 POST
请求,介绍了如何传递 json
类型和 application/x-www-form-urlencoded
类型的 body
参数。对于 HTTP
中的 query
参数和 body
参数的如何传递,上下两篇文章已经通过例子进行介绍。虽然举的例子是 GET
和 POST
请求,如果想要调用 PUT
、DELETE
等请求,只需要在 NewRequestWithContext
函数中,指定第二个参数为 http.MethodPut
、http.MethodDelete
等就行。