Go语言基础(四)客户端模拟发送HTTP请求

在Golang中web开发中net/http是经常用到的包,在这个包中包含了各种请求与响应的方式,下面我会一一进行介绍。

关键词:golang

GET请求

不带参数的GET请求

直接使用http.Get()函数,返回一个*http.Response类型的变量,使用os.ReadAll(resp.Body)会读取相应后内容

1
2
3
4
5
6
7
8
9
10
11
12
func SendSimpleGetRequest() {
response, err := http.Get("https://www.baidu.com")
if err != nil {
panic(err)
}
defer response.Body.Close()
s, err := io.ReadAll(response.Body)
fmt.Println(string(s))
if err != nil {
panic(err)
}
}

携带参数的GET请求

使用url.Values{}返回一个map[string][]string类型,不推荐直接在url地址中携带。

可以使用params.Encode()对中文进行编码,防止数据在传输过程中出错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func SendComplexGetRequest() {
params := url.Values{}
urlObj, err := url.Parse("http://www.baidu.com")
if err != nil {
panic(err)
}
params.Set("a", "afds")
params.Set("id", string("1"))

// 如果有中文参数,这个操作会对中文参数进行解析
urlObj.RawQuery = params.Encode()
urlPath := urlObj.String()
resp, err := http.Get(urlPath)
if err != nil {
panic(err)
}
defer resp.Body.Close()
response, err := io.ReadAll(resp.Body)
fmt.Printf("response: %s\n", response)
if err != nil {
panic(err)
}
}

Post 请求

Post请求:application/x-www-form-urlencoded

这应该是最常见的 POST 提交数据的方式了。浏览器的原生

表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据

1
2
3
4
5
6
7
8
9
10
11
12
13
func httpPostForm() {
// params := url.Values{}
// params.Set("id", "123")
params := url.Values{
"key": {"value"},
"id": {"123"},
}
resp, _ := http.PostForm("http://baidu.com", params)
fmt.Println("request header[Content-Type]:", resp.Request.Header["Content-Type"])
defer resp.Body.Close()
s, _ := io.ReadAll(resp.Body)
fmt.Println(string(s))
}

Post请求:multipart/form-data

multipart/form-data的基础方法是post,其请求头必须包含一个特殊的头信息:Content-Type,值为multipart/form-data,同时还需要规定一个内容分割符用于分割请求体中的多个post的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
func httpPostMultipartField() {

url := "/qb/api/v2/auth/login"
method := "POST"

body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
err := writer.WriteField("username", "fly97")
if err != nil {
panic(err)
}
err = writer.WriteField("password", "xxxx")
if err != nil {
panic(err)
}
err = writer.Close()
if err != nil {
panic(err)
}

req, err := http.NewRequest(method, url, body)
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
fmt.Println("request header[Content-Type]:", resp.Request.Header["Content-Type"])
defer resp.Body.Close()

response, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Printf("response: %s", response)
}

客户端通用模式

一般遵循以下的顺序:

  1. 使用http.Client{}实例化一个客户端;
  2. 使用http.NewRequest()新创建一个请求;
  3. 设置请求头req.Header.Set()
  4. 使用client.Do(req)发送请求;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
func httpDo() {
client := &http.Client{}

urlmap := url.Values{}

urlmap.Add("client_id", "esss")
urlmap.Add("client_secret", "sk")
parms := ioutil.NopCloser(strings.NewReader(urlmap.Encode())) //把form数据编下码
req, err := http.NewRequest("POST", "www.baidu.com", parms)
if err != nil {
// handle error
}

req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Cookie", "name=anny")

resp, err := client.Do(req)

defer resp.Body.Close()

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle error
}

fmt.Println(string(body))
}