Go 通过 net/http 包提供了强大的 HTTP 客户端功能。
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
// 发送 GET 请求
resp, err := http.Get("https://httpbin.org/get")
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("读取失败:", err)
return
}
fmt.Println("状态码:", resp.StatusCode)
fmt.Println("响应体:", string(body))
}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
// 准备请求数据
data := map[string]string{
"name": "Alice",
"age": "30",
}
jsonData, _ := json.Marshal(data)
// 发送 POST 请求
resp, err := http.Post(
"https://httpbin.org/post",
"application/json",
bytes.NewBuffer(jsonData),
)
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println("响应:", string(body))
}
package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
// 准备表单数据
formData := url.Values{}
formData.Set("username", "alice")
formData.Set("password", "123456")
// 发送 POST 表单请求
resp, err := http.PostForm(
"https://httpbin.org/post",
formData,
)
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println("响应:", string(body))
}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
// 准备请求体
data := map[string]string{"name": "Alice"}
jsonData, _ := json.Marshal(data)
// 创建请求
req, err := http.NewRequest(
"POST",
"https://httpbin.org/post",
bytes.NewBuffer(jsonData),
)
if err != nil {
fmt.Println("创建请求失败:", err)
return
}
// 设置请求头
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer token123")
req.Header.Set("X-Custom-Header", "custom-value")
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println("响应:", string(body))
}
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://httpbin.org/headers", nil)
// 设置单个请求头
req.Header.Set("Authorization", "Bearer token123")
// 添加请求头(可添加多个同名头)
req.Header.Add("Accept", "application/json")
req.Header.Add("Accept", "text/html")
// 设置 User-Agent
req.Header.Set("User-Agent", "MyGoClient/1.0")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
package main
import (
"fmt"
"net/http"
)
func main() {
resp, err := http.Get("https://httpbin.org/get")
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
// 获取单个响应头
contentType := resp.Header.Get("Content-Type")
fmt.Println("Content-Type:", contentType)
// 遍历所有响应头
fmt.Println("\n所有响应头:")
for key, values := range resp.Header {
for _, value := range values {
fmt.Printf("%s: %s\n", key, value)
}
}
}
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://httpbin.org/cookies", nil)
// 添加 Cookie
cookie1 := &http.Cookie{
Name: "session_id",
Value: "abc123",
}
cookie2 := &http.Cookie{
Name: "user_id",
Value: "user001",
}
req.AddCookie(cookie1)
req.AddCookie(cookie2)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
package main
import (
"fmt"
"io"
"net/http"
"net/http/cookiejar"
)
func main() {
// 创建 Cookie Jar
jar, _ := cookiejar.New(nil)
// 创建带有 Cookie Jar 的客户端
client := &http.Client{
Jar: jar,
}
// 第一次请求(服务器会设置 Cookie)
resp1, _ := client.Get("https://httpbin.org/cookies/set?session_id=abc123")
resp1.Body.Close()
// 第二次请求(自动携带 Cookie)
resp2, _ := client.Get("https://httpbin.org/cookies")
defer resp2.Body.Close()
body, _ := io.ReadAll(resp2.Body)
fmt.Println(string(body))
}
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
// 创建带超时的客户端
client := &http.Client{
Timeout: 5 * time.Second,
}
resp, err := client.Get("https://httpbin.org/delay/3")
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
fmt.Println("状态码:", resp.StatusCode)
}
package main
import (
"context"
"fmt"
"io"
"net/http"
"time"
)
func main() {
// 创建带超时的 Context
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
// 创建请求
req, _ := http.NewRequestWithContext(ctx, "GET", "https://httpbin.org/delay/5", nil)
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("请求失败:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
package main
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
func uploadFile(filename string) error {
// 打开文件
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
// 创建 multipart writer
var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
// 添加文件字段
part, _ := writer.CreateFormFile("file", filename)
io.Copy(part, file)
// 添加其他字段
writer.WriteField("description", "文件描述")
writer.Close()
// 发送请求
req, _ := http.NewRequest("POST", "https://httpbin.org/post", &buf)
req.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
return nil
}
func main() {
uploadFile("test.txt")
}
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func downloadFile(url, filename string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
// 创建文件
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
// 写入文件
_, err = io.Copy(file, resp.Body)
return err
}
func main() {
err := downloadFile("https://example.com/file.txt", "downloaded.txt")
if err != nil {
fmt.Println("下载失败:", err)
return
}
fmt.Println("下载成功")
}
package main
import (
"crypto/tls"
"fmt"
"io"
"net/http"
)
func main() {
// 创建跳过证书验证的客户端
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
resp, _ := client.Get("https://example.com")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
package main
import (
"crypto/tls"
"crypto/x509"
"io"
"net/http"
"os"
)
func main() {
// 读取证书
caCert, _ := os.ReadFile("ca.crt")
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// 创建客户端
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: caCertPool,
},
},
}
resp, _ := client.Get("https://example.com")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
println(string(body))
}
package main
import (
"fmt"
"io"
"net/http"
"net/url"
)
func main() {
// 设置代理
proxyURL, _ := url.Parse("http://proxy.example.com:8080")
client := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
}
resp, _ := client.Get("https://httpbin.org/ip")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
// 使用环境变量中的代理设置
client := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
},
}
resp, _ := client.Get("https://httpbin.org/ip")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
package main
import (
"fmt"
"net/http"
"time"
)
func main() {
// 配置连接池
transport := &http.Transport{
MaxIdleConns: 100, // 最大空闲连接数
MaxIdleConnsPerHost: 10, // 每个主机的最大空闲连接数
IdleConnTimeout: 90 * time.Second, // 空闲连接超时
DisableKeepAlives: false, // 启用 Keep-Alive
}
client := &http.Client{
Transport: transport,
Timeout: 30 * time.Second,
}
resp, _ := client.Get("https://httpbin.org/get")
defer resp.Body.Close()
fmt.Println("状态码:", resp.StatusCode)
}
package main
import (
"fmt"
"net/http"
)
func main() {
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse // 不跟随重定向
},
}
resp, _ := client.Get("https://httpbin.org/redirect/1")
defer resp.Body.Close()
fmt.Println("状态码:", resp.StatusCode)
fmt.Println("Location:", resp.Header.Get("Location"))
}
package main
import (
"fmt"
"net/http"
)
func main() {
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
fmt.Printf("重定向到: %s\n", req.URL)
if len(via) >= 10 {
return fmt.Errorf("重定向次数过多")
}
return nil
},
}
resp, _ := client.Get("https://httpbin.org/redirect/3")
defer resp.Body.Close()
fmt.Println("最终状态码:", resp.StatusCode)
}
本章详细介绍了 Go 语言的 HTTP 客户端编程:
http.NewRequest 创建请求HTTP 客户端是进行网络编程的基础,掌握它能让你更好地与外部服务交互。在下一章中,我们将学习如何构建 HTTP 服务器。