标准库中的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])
}
http.Post() returned statuts code 200, truncated text:
{
"args": {},
"data": "text we send",
"files": {},
"form": {},
"headers": {
...
发起POST最简单的方法是使用http.Client.Post(url string, contentType string, body io.Reader)
。
在上例中,我们发送了原始文本。在大多数情况下,服务端期望请求体是URL编码(Url-Encoded)后的格式。
基本的HEAD请求
跟GET用法一样,只改一下方法名http.Client.Head(uri string)
。