36 HTTP客户端

标准库中的net/http包提供了发起HTTP请求的功能。

在示例中,我们使用httpbin.org,它是一个聪明的HTTP服务,可以返回指定的HTTP响应,它用于演示HTTP协议的各个方面非常便利。

基本的GET请求

http.Get()只是http.DefaultClient的封装,后者是*http.Client类型的变量打包。

最好不要使用http.Get,因为它默认是没有超时的,这意味着它在连接到慢的或有缺陷的或恶意的服务上时永远等待。

译者注:对于网络服务来说,慢比错更可怕。慢意味着不确定性,如果不设置合适的超时限制,服务将被拖垮。

package main

import (
	"fmt"
	"log"
	"net/http"
	"time"
)

func main() {
	client := &http.Client{}
	client.Timeout = time.Millisecond * 100

	uri := "https://httpbin.org/delay/3"
	resp, err := client.Get(uri)
	if err != nil {
		log.Fatalf("http.Get() failed with '%s'\n", err)
	}
	fmt.Println(resp)
}

如上所示,创建和使用自定义的http.Client是很容易的。

在上例中,我们设置了非常短的超时限制,以此演示因超时而取消连接。

在实际编程中,应该采用更长的超时时间,比如15秒(确切的超时时长应视情况而定)。

基本的POST请求

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

func main() {
	client := &http.Client{}
	client.Timeout = time.Second * 15

	uri := "https://httpbin.org/post"
	body := bytes.NewBufferString("text we send")
	resp, err := client.Post(uri, "text/plain", body)
	if err != nil {
		log.Fatalf("client.Post() failed with '%s'\n", err)
	}
	defer resp.Body.Close()
	d, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("http.Get() failed with '%s'\n", err)
	}
	fmt.Printf("http.Post() returned statuts code %d, truncated text:\n%s...\n", resp.StatusCode, string(d)[:93])
}

发起POST最简单的方法是使用http.Client.Post(url string, contentType string, body io.Reader)

在上例中,我们发送了原始文本。在大多数情况下,服务端期望请求体是URL编码(Url-Encoded)后的格式。

基本的HEAD请求

跟GET用法一样,只改一下方法名http.Client.Head(uri string)

最后更新于