Golang如何在SetupClient函数else分支内修改返回的*http.Client值?
Go语言SetupClient函数返回代理客户端不生效问题修复
问题根因
你现在的代码无法在else分支返回代理客户端,核心原因有3个:
http.Request是一次性对象,直连请求已经消费过req实例,直接复用给代理客户端发起第二次请求会直接报错,触发err != nil的分支,自然走不到内部的return逻辑- 所有响应的
resp.Body都没有主动关闭,多次循环后会占用大量系统资源,引发后续请求异常 - 代理请求失败后没有任何兜底逻辑,会直接进入下一轮循环,看起来就像返回值没有更新
修复代码
func SetupClient() *http.Client { // 正则和固定配置提出来,不用每次循环重复构造 re := regexp.MustCompile(`:"(.*)`) tlsConfig := &tls.Config{InsecureSkipVerify: true} PTransport := &http.Transport{TLSClientConfig: tlsConfig, Proxy: http.ProxyFromEnvironment} directTransport := &http.Transport{TLSClientConfig: tlsConfig} for { fmt.Printf(" trying direct connection \n") // 每次请求重新构造req,不要复用 req, err := http.NewRequest("GET", "https://192.168.1.98:4443/api/endpointx", nil) if err != nil { fmt.Println("构造请求失败:", err) time.Sleep(5 * time.Second) continue } // 统一设置请求头 req.Header.Set("Cookie", "JSESSIONID=shszrhdrhdrhjdhdr") req.Header.Set("Referer", "https://aaegesgsegesgegeg") req.Header.Set("Upgrade-Insecure-Requests", "1") req.Header.Set("Connection", "close") req.Header.Set("Accept-Language", "it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3") req.Header.Set("Accept", "*/*") req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0") time.Sleep(5 * time.Second) // 先尝试直连 directClient := &http.Client{Transport: directTransport} resp, err := directClient.Do(req) if err == nil { body, _ := ioutil.ReadAll(resp.Body) _ = resp.Body.Close() // 用完立即关闭body match := re.FindStringSubmatch(string(body)) if len(match) < 2 { // 加匹配校验,避免索引越界panic fmt.Println("正则匹配失败") continue } fmt.Println("quello che viene matchato è:", match[1]) if strings.Contains(string(body), "aaaaaaaa") { fmt.Printf(" inside IF\n ") return directClient } else { fmt.Printf(" inside else\n ") // 代理请求重新构造req proxyReq, _ := http.NewRequest("GET", "https://192.168.1.98:4443/api/endpointx", nil) proxyReq.Header = req.Header.Clone() // 复用之前的请求头 proxyClient := &http.Client{Transport: PTransport} proxyResp, err := proxyClient.Do(proxyReq) if err == nil { proxyBody, _ := ioutil.ReadAll(proxyResp.Body) _ = proxyResp.Body.Close() if strings.Contains(string(proxyBody), match[1]) { return proxyClient } } else { fmt.Println("代理请求失败:", err) } } } else { fmt.Println("直连请求失败:", err) } } }
关键修改说明
- 把正则、TLS配置、传输层实例提到循环外,避免每次循环重复创建,减少不必要的性能开销
- 每次发起新请求都重新构造Request实例,不要复用已经被消费过的请求对象
- 所有resp.Body使用完后立即关闭,避免资源泄漏
- 增加正则匹配结果校验,避免匹配失败后索引越界panic
- 补充各环节错误日志打印,方便排查问题
内容的提问来源于stack exchange,提问作者ryout
相关产品推荐
相关产品推荐

