如何实现带代理启用/禁用选项的Go语言网页请求函数?
没问题,我帮你完善这个函数,实现根据useProxy参数动态切换Tor代理的功能。这里是完整的可运行代码,还有关键细节的解释:
import ( "io/ioutil" "log" "net/http" "net/url" "time" ) var torProxy string = "socks5://127.0.0.1:9050" func getPage(webUrl string, useProxy bool) ([]byte, error) { // 初始化基础Transport(无代理) transport := &http.Transport{ DisableKeepAlives: true, } var clientTransport http.RoundTripper = transport if useProxy { // 如果启用代理,解析Tor代理URL并创建带代理的Transport torProxyUrl, err := url.Parse(torProxy) if err != nil { return nil, err } torTransport := &http.Transport{ Proxy: http.ProxyURL(torProxyUrl), DisableKeepAlives: true, // 和基础Transport保持一致的配置 } clientTransport = torTransport } // 创建HTTP客户端,设置超时和对应的Transport client := &http.Client{ Transport: clientTransport, Timeout: 10 * time.Second, // 设置合理的超时时间,避免无限等待 } // 发起请求 req, err := http.NewRequest("GET", webUrl, nil) if err != nil { return nil, err } // 可选:添加User-Agent模拟浏览器请求,避免被目标网站拦截 req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() // 务必关闭响应体,防止内存泄漏 // 读取响应内容 body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } // 可选:检查响应状态码,非200时打个日志提示 if resp.StatusCode != http.StatusOK { log.Printf("请求返回非成功状态: %s", resp.Status) } return body, nil }
关键细节说明:
- 返回值调整:把原函数改成返回响应内容和错误,这样调用方可以灵活处理结果(比如保存到文件、解析HTML)和异常情况,比无返回值的设计更实用。
- 代理动态切换:通过
useProxy参数判断是否启用Tor代理,用http.RoundTripper接口类型统一接收两种Transport,简化客户端的初始化逻辑。 - 配置一致性:带代理的
torTransport也设置了DisableKeepAlives: true,和基础Transport保持相同的配置,避免出现意料之外的行为差异。 - 超时设置:给
http.Client加上10秒的超时时间,防止请求因为网络问题长时间挂起,占用资源。 - 资源清理:用
defer resp.Body.Close()确保响应体被关闭,这是Go HTTP请求的最佳实践,能有效避免内存泄漏。 - 请求头优化:添加了常见的User-Agent,很多网站会拦截没有UA的请求,这样能提升请求成功率。
内容的提问来源于stack exchange,提问作者kingcope
相关产品推荐
相关产品推荐

