package main import ( "fmt" "net/http" "time" ) func main() { // 创建一个自定义的 Transport 实例 //transport := &http.Transport{ // Proxy: func(req *http.Request) (*url.URL, error) { // // return url.Parse("http://127.0.0.1:1081") // return url.Parse("socks5://127.0.0.1:1080") // }, //} // 堆代码 duidaima.com // 创建一个自定义的 Client 实例 client: = & http.Client { //Transport: transport, // 设置代理 Timeout: time.Second * 3, // 设置超时 } urlStr: = "https://www.google.com/" // 发送 GET 请求 resp, err: = client.Get(urlStr) if err != nil { // 处理错误 fmt.Println("发生了错误:err", err) return } defer resp.Body.Close() // 处理响应 fmt.Println(resp.StatusCode) }输出: 发生了错误:err Get "https://www.google.com/": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
在 Go 的 http 包中,Client 类型代表了 HTTP 客户端。在 Client 中有一个名为 Transport 的字段,它是一个 http.RoundTripper 接口类型的值,用于处理 HTTP 请求和响应的传输细节。通过设置 Transport 字段,可以对 HTTP 请求进行一些自定义设置,比如设置代理、设置超时、设置 TLS 客户端证书等。Transport 字段提供了一些默认实现,也可以通过实现 http.RoundTripper 接口来自定义实现。
transport := &http.Transport{ Proxy: func(req *http.Request) (*url.URL, error) { return url.Parse("http://127.0.0.1:8888") }, } client := &http.Client{ Transport: transport, }在上面的代码中,通过自定义 Transport 并设置代理来实现将所有 HTTP 请求通过本地的代理服务器进行转发。这样就可以在代理服务器上进行一些中间人攻击的操作,如抓包、篡改请求等。
func fetchURL(url string) (string, error) { // 创建一个自定义的 Transport 实例 transport := &http.Transport{ Proxy: func(req *http.Request) (*url.URL, error) { return url.Parse("http://127.0.0.1:1080") // 设置代理 }, } // 创建一个自定义的 Client 实例 client := &http.Client{ Transport: transport, // 设置 Transport Timeout: time.Second * 3, // 设置超时 } // 发送 GET 请求 resp, err := client.Get(url) if err != nil { // 处理错误 return "", err } defer resp.Body.Close() // 读取响应内容 body, err := ioutil.ReadAll(resp.Body) if err != nil { // 处理错误 return "", err } // 返回响应内容 return string(body), nil } func main() { urls := []string{ "http://example.com", "http://example.org", "http://example.net", } // 遍历 URL 列表,并发送请求 for _, url := range urls { resp, err := fetchURL(url) if err != nil { fmt.Printf("fetch %s error: %s\n", url, err) } else { fmt.Printf("fetch %s success: %s\n", url, resp) } } }
此外,还可以尝试对 Transport 的 MaxIdleConnsPerHost 和 MaxIdleConns 进行调整,以确保连接复用时不会出现连接超时或连接关闭的问题。
当http client创建一个连接时,它将尝试重用现有的空闲连接。如果连接池中没有空闲连接,则http client将创建一个新的连接。如果连接池中的空闲连接已达到MaxIdleConns或MaxIdleConnsPerHost,则http client将关闭连接。
transport := &http.Transport{ MaxIdleConnsPerHost: 10, // 每个主机最大空闲连接数 MaxIdleConns: 100, // 最大空闲连接数 }其中,MaxIdleConnsPerHost 表示每个主机最大的空闲连接数,MaxIdleConns 表示所有主机的最大空闲连接数。您可以根据实际情况进行调整。需要注意的是,如果 MaxIdleConnsPerHost 设置的太小,可能会导致无法复用连接,从而增加了连接的建立和关闭成本;如果设置的太大,可能会占用过多的系统资源。