Go发起HTTP请求

基本方法请求

1. GET请求

使用http.Get快速发起一个GET请求

1
2
3
4
5
6
7
8
9
func get() {
resp, err := http.Get("http://httpbin.org/get")
if err != nil {
panic(err)
}
defer func() { _ = resp.Body.Close() }()
content, err := io.ReadAll(resp.Body)
fmt.Println(string(content))
}

content返回的是一个字节数组

2.POST请求

使用http.Post可以快速发起一个POST请求

1
2
3
4
5
6
7
8
9
func post() {
resp, err := http.Post("http://httpbin.org/post", "", nil)
if err != nil {
panic(err)
}
defer func() { _ = resp.Body.Close() }()
content, err := io.ReadAll(resp.Body)
fmt.Println(string(content))
}

与http.Get不同的是http.Post有三个参数

1
http.Post(url string, bodyType string, body io.Reader)

3.PUT以及其他请求方法

对于除了GETPOST之外的请求方法。Go并没有提供想http.Gethttp.Post这样的比较便捷的方法。

对于其他请求方法需要我们先用http.NewRequest方法新建一个请求

然后再用http.DefaultClient.Do方法发送请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func put() {
resp, err := http.NewRequest(http.MethodPut, "http://httpbin.org/put", nil)
if err != nil {
panic(err)
}

do, err := http.DefaultClient.Do(resp) //相当于发送动作
if err != nil {
panic(err)
}
defer func() { _ = do.Body.Close() }()
rsp, err := io.ReadAll(do.Body)
if err != nil {
panic(err)
}
fmt.Println(string(rsp))

}

为请求加一个GET传参以及请求头

  1. 为请求加一个get请求有两种方法

    • 第一个是在我们的url后面直接拼接就行

      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
      package main

      import (
      "fmt"
      "io"
      "net/http"
      )

      func prinBody(r *http.Response) {
      defer r.Body.Close()
      data, err := io.ReadAll(r.Body)
      if err != nil {
      panic(err)
      }
      fmt.Println(string(data))
      }

      func main() {
      request, err := http.NewRequest(http.MethodGet, "http://httpbin.org/get?name=1", nil)
      if err != nil {
      panic(err)
      }
      rsp, _ := http.DefaultClient.Do(request)
      prinBody(rsp)
      }

    • 第二个就是使用net/http包中的url.values

      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
      package main

      import (
      "fmt"
      "io"
      "net/http"
      "net/url"
      )

      func prinBody(r *http.Response) {
      defer r.Body.Close()
      data, err := io.ReadAll(r.Body)
      if err != nil {
      panic(err)
      }
      fmt.Println(string(data))
      }

      func main() {
      request, err := http.NewRequest(http.MethodGet, "http://httpbin.org/get?name=1", nil)
      if err != nil {
      panic(err)
      }

      params := make(url.Values)
      params.Add("name", "1")
      request.URL.RawQuery = params.Encode()
      do, err := http.DefaultClient.Do(request)
      prinBody(do)

      }

  2. 修改请求头

请求头修改可以直接在request上面进行修改,比如request.Header.Add("Cookie", "set-cookies")

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
package main

import (
"fmt"
"io"
"net/http"
)

func prinBody(r *http.Response) {
defer r.Body.Close()
data, err := io.ReadAll(r.Body)
if err != nil {
panic(err)
}
fmt.Println(string(data))
}

func main() {
request, err := http.NewRequest(http.MethodGet, "http://httpbin.org/get?name=1", nil)
if err != nil {
panic(err)
}

request.Header.Add("Cookie", "set-cookies") //设置请求头
do, err := http.DefaultClient.Do(request)
prinBody(do)

}

响应信息

获取响应信息

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
package main

import (
"fmt"
"io"
"net/http"
)

func responseBody(r *http.Response) {
data, err := io.ReadAll(r.Body)
if err != nil {
panic(err)
}

fmt.Println(string(data))
}

func main() {
request, err := http.NewRequest(http.MethodGet, "http://httpbin.org/get", nil)
if err != nil {
panic(err)
}
do, err := http.DefaultClient.Do(request)
defer do.Body.Close()
responseBody(do)

}

获取相应状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"fmt"
"net/http"
)

func status(r *http.Response) {
fmt.Println("response Status:", r.Status) //状态描述
fmt.Println("response StatusCode:", r.StatusCode) //状态码
}

func main() {
request, err := http.NewRequest(http.MethodGet, "http://httpbin.org/get", nil)
if err != nil {
panic(err)
}
do, err := http.DefaultClient.Do(request)
defer do.Body.Close()
status(do)

}

获取相应头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"fmt"
"net/http"
)

func header(r *http.Response) {
fmt.Println(r.Header.Get("content-type"))

}

func main() {
request, err := http.NewRequest(http.MethodGet, "http://httpbin.org/get", nil)
if err != nil {
panic(err)
}
do, err := http.DefaultClient.Do(request)
defer do.Body.Close()
header(do)

}

请求下载文件

使用io.copy方法将响应读取到的io流保存到文件

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
package main

import (
"fmt"
"io"
"net/http"
"os"
)

func downloadFile(url string, filepath string) {
req, err := http.Get(url)
if err != nil {
panic(err)
}
defer func() { _ = req.Body.Close() }()

f, err := os.Create(filepath)
if err != nil {
panic(err)
}
defer func() { _ = f.Close() }()
written, err := io.Copy(f, req.Body)
if err != nil {
panic(err)
}
fmt.Printf("%d bytes downloaded\n", written)
}

func main() {
target := "https://xxx"
downloadFile(target, "tou.jpg")

}

显示下载进度

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package main

import (
"fmt"
"io"
"net/http"
"os"
)

func downloadFileProgress(url string, filepath string) {
req, err := http.Get(url)
if err != nil {
panic(err)
}
defer func() { _ = req.Body.Close() }()

f, err := os.Create(filepath)
if err != nil {
panic(err)
}
defer func() { _ = f.Close() }()

reader := &Reader{
Reader: req.Body,
Total: req.ContentLength,
}

written, err := io.Copy(f, reader)
if err != nil {
panic(err)
}
fmt.Printf("%d bytes downloaded\n", written)
}

type Reader struct {
io.Reader
Total int64
Current int64
}

func (r *Reader) Read(p []byte) (n int, err error) {
n, err = r.Reader.Read(p)
if n > 0 {
r.Current += int64(n)
if r.Total > 0 {
fmt.Printf("Downloaded %d%%\n", r.Current*100/r.Total)
}
}
return n, err
}

func main() {
target := "https://i0.hdslb.com/bfs/sycp/creative_img/202410/7acb2fc39310d2f82f69726b147f491f.jpg@800w_512h_!web-home-carousel-cover.avif" //图片url
downloadFileProgress(target, "tou.jpg")

}

POST提交form表单或者json数据

http.Post方法第一个参数是我们要发送数据的url第二个参数是Postcontent-type,第三个就是要发送的数据是io.Reader类型的参数

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
package main

import (
"fmt"
"io"
"net/http"
"net/url"
"strings"
)

func postFrom(ur string) {
param := make(url.Values)
param.Add("name", "Yliken")
param.Encode()

req, err := http.Post(ur,
"application/x-www-form-urlencoded",
strings.NewReader(param.Encode()),
)
if err != nil {
fmt.Println(err)
}

defer func() { _ = req.Body.Close() }()

rsp, err := io.ReadAll(req.Body)
fmt.Println(string(rsp))

}

func main() {
target := "http://httpbin.org/post"
postFrom(target)
}

用post发送一个json数据

用go发生json数据,需要我们先用json表示出我们要发送的数据。如何再用encoding/json包中的json.Marshal函数进行json编码

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
40
41
package main

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
)

func postJson(ur string) {
Json := struct {
Name string `json:"name"`
Age int `json:"age"`
}{
Name: "Yliken",
Age: 18,
}

payload, _ := json.Marshal(Json)
req, err := http.Post(ur,
"application/json",
bytes.NewReader(payload),
)
if err != nil {
fmt.Println(err)
}

defer func() { _ = req.Body.Close() }()

rsp, err := io.ReadAll(req.Body)
fmt.Println(string(rsp))

}

func main() {
target := "http://httpbin.org/post"
postJson(target)
}