Go 语言提供了 net/http 包,协助用户实施与 HTTP 协议相关的开发任务。该包既提供了 HTTP 服务器 实现,又提供了 客户端 实现。这里记录使用 Go发起 http 请求。
net/http:https://studygolang.com/static/pkgdoc/pkg/net_http.htm
http.Response
Response 是 HTTP 请求后的响应,下面是我们可以从中获取到的内容:
读取 Body 信息,需要注意的是 :对 Body 的处理需要在其未关闭完之前进行
1 2 3 4 5 6 7 8 9 10 11 12
| func GetReqBody(url string) (string, error) { resp, err := http.Get(url) if err != nil { return "", err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return "", err } return string(body), nil }
|
Header 结构体方法:

Get 请求
1 2 3 4 5 6 7 8 9 10 11 12 13
| func main() { url := "https://httpbin.org/get" resp, err := http.Get(url) if err != nil { log.Fatal(err) } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(string(body)) }
|
Post 请求
Post 请求可以使用 http.Post 或者 http.PostForm 方法,使用方法如下:
http.Post 方法:
1
| func Post(url string, bodyType string, body io.Reader) (resp Response, err error)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| func main() { url := "https://httpbin.org/post" payload := []byte(`{"key": "value"}`)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(payload)) if err != nil { log.Fatal(err) } defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) }
fmt.Println(string(body)) }
|
http.PostForm 方法:
1
| func PostForm(url string, data url.Values) (resp Response, err error)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| func main() { targetUrl := "https://httpbin.org/post" values := url.Values{ "key1": {"value1"}, "key2": {"value2"}, } resp, err := http.PostForm(targetUrl, values) if err != nil { log.Fatal(err) } defer resp.Body.Close()
body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) }
fmt.Println(string(body)) }
|
HTTP Client
struct
1 2 3 4 5 6 7 8 9 10
| type Client struct { Transport RoundTripper CheckRedirect func(req Request, via []Request) error Jar CookieJar Timeout time.Duration }
|
Client 的 Transport 字段一般会含有内部状态(缓存 TCP 连接),因此 Client 类型值应尽量被重用而不是每次需要都创建新的。
Client 的 Transport 类型都可以安全的被多个 go 程同时使用。出于效率考虑,应该一次建立、尽量重用。
Transport
struct
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
| type Transport struct { Proxy func(Request) (url.URL, error) Dial func(network, addr string) (net.Conn, error) TLSClientConfig tls.Config TLSHandshakeTimeout time.Duration DisableKeepAlives bool DisableCompression bool MaxIdleConnsPerHost int ResponseHeaderTimeout time.Duration }
|
Proxy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| func main() { targetUrl := "https://example.com"
tr := &http.Transport{ Proxy: func(req http.Request) (url.URL, error) { return url.Parse("http://your-proxy-server:port") }, }
client := &http.Client{ Transport: tr, } resp, err := client.Get(targetUrl) if err != nil { panic(err) } defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status) }
|
TLSClientConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| func main() { url := "https://example.com"
tr := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }
client := &http.Client{ Transport: tr, }
resp, err := client.Get(url) if err != nil { panic(err) } defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status) }
|
Timeout
http.Get 和 http.Post 都是没有设置超时的,在生产业务需要设置超时时间,以免 goroutine 被超时请求阻塞而停止响应。
1 2 3 4 5
| var client = &http.Client{ Timeout: time.Second 5, }
rsps, err := client.Get("http://example.com")
|
CheckRedirect
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| func main() { CheckRedirect := func(req http.Request, via []http.Request) error { if len(via) >= 3 { return errors.New("stopped after 3 redirects") } return nil } client := &http.Client{ CheckRedirect: CheckRedirect, Timeout: 15 time.Second, } resp, err := client.Get("https://httpbin.org/get") if err != nil { log.Fatal(err) } defer resp.Body.Close()
body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(string(body)) }
|
http.NewRequest
http.NewRequest 是新建一个请求,然后通过 client.Do 发起请求,对于 Get、Post 来说有更多的操作空间,如自定义 Header、Cookie 等操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| func main() { client := &http.Client{ Timeout: 15 time.Second, } request, err := http.NewRequest("GET", "https://httpbin.org/get", nil) if err != nil { log.Fatal(err) } request.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36") request.AddCookie(&http.Cookie{ Name: "name", Value: "fuyoumingyan", }) response, err := client.Do(request) if err != nil { log.Fatal(err) } body, err := io.ReadAll(response.Body) if err != nil { log.Fatal(err) } fmt.Println(string(body)) }
|
