{"id":10006789,"date":"2022-11-03T21:49:01","date_gmt":"2022-11-03T13:49:01","guid":{"rendered":"https:\/\/ityet.com\/?p=10006789"},"modified":"2022-11-03T21:49:01","modified_gmt":"2022-11-03T13:49:01","slug":"%e4%bd%bf%e7%94%a8%e5%bb%ba%e9%80%a0%e8%80%85%e6%a8%a1%e5%bc%8f%e5%b0%81%e8%a3%85go%e7%9a%84http%e5%ba%93","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006789","title":{"rendered":"\u4f7f\u7528\u5efa\u9020\u8005\u6a21\u5f0f\u5c01\u88c5go\u7684http\u5e93"},"content":{"rendered":"<pre><code>\u5728\u65e5\u5e38\u5f00\u53d1\u4e2d\u7ecf\u5e38\u4f1a\u7528\u5230http\u5e93\u6765\u53d1\u9001\u8bf7\u6c42\uff0c\u5c31\u5c06\u5e38\u7528\u7684\u8bf7\u6c42\u65b9\u6cd5\u5c01\u88c5\u4e86\u4e00\u4e2a\u5e93\uff0c\u7075\u6d3b\u53c8\u597d\u7528\u3002\n\n\u8fd9\u91cc\u7528\u5230\u4e86\u5efa\u9020\u8005\u6a21\u5f0f\uff0c\u7c7b\u4f3c\u7684\u4f7f\u7528\u573a\u666f\u90fd\u53ef\u4ee5\u8fd9\u6837\u6765\u5b9e\u73b0\uff1a\n<\/code><\/pre>\n<p><strong>\u5177\u4f53\u5b9e\u73b0<\/strong><\/p>\n<pre><code class=\"go\">package requests\n\nimport (\n    &quot;bytes&quot;\n    &quot;context&quot;\n    &quot;encoding\/json&quot;\n    &quot;errors&quot;\n    &quot;fmt&quot;\n    &quot;io\/ioutil&quot;\n    &quot;net\/http&quot;\n    &quot;net\/url&quot;\n    &quot;strings&quot;\n    &quot;time&quot;\n)\n\nconst (\n    contentType = &quot;Content-Type&quot;\n)\n\ntype HttpSend struct {\n    ctx            context.Context   \/\/ \u4e0a\u4e0b\u6587\n    client         *http.Client      \/\/ \u5ba2\u6237\u7aef\n    request        *http.Request     \/\/ \u8bf7\u6c42\u4f53\n    url, httpProxy string            \/\/ \u8bf7\u6c42\u8def\u5f84\n    getValue       interface{}       \/\/ get\u8bf7\u6c42\u4f53\n    postValue      interface{}       \/\/ post\u8bf7\u6c42\u4f53\n    postFormValue  url.Values        \/\/ form-data post\u8bf7\u6c42\u4f53\n    header         map[string]string \/\/ header\n    timeout        time.Duration     \/\/ \u8d85\u65f6\u65f6\u95f4\n    tryNum         int               \/\/ \u91cd\u8bd5\u6b21\u6570\n    doNum          int               \/\/ \u5df2\u91cd\u8bd5\u6b21\u6570\n    intervalTime   time.Duration     \/\/ \u91cd\u8bd5\u95f4\u9694\u65f6\u95f4\n    err            error             \/\/ \u9519\u8bef\n}\n\n\/\/ \u4f7f\u7528\u5efa\u9020\u8005\u6a21\u5f0f\u521d\u59cb\u5316HttpClient\nfunc NewHttpClient(ctx context.Context, options ...HttpOptions) *HttpSend {\n    client := new(HttpSend)\n    client.ctx = ctx\n    for i := 0; i &lt; len(options); i++ {\n        options[i](client)\n    }\n    client.NewClient(ctx)\n    if client.timeout != 0 {\n        client.client.Timeout = client.timeout\n    }\n    return client\n}\n\n\/\/ \u5b9e\u4f8b\u5316HttpClient\nfunc (h *HttpSend) NewClient(ctx context.Context) {\n    h.client = new(http.Client)\n    if h.httpProxy != &quot;&quot; {\n        var proxyUrl *url.URL\n        proxyUrl, h.err = url.Parse(h.httpProxy)\n        if h.err != nil {\n            log.Errorf(ctx, fmt.Sprintf(&quot;\u521d\u59cb\u5316httpClient-httpProxy\u89e3\u6790\u9519\u8bef\uff0c error:%s&quot;, h.err))\n        }\n        h.client.Transport = &amp;http.Transport{\n            Proxy: http.ProxyURL(proxyUrl),\n        }\n    }\n}\n\n\/\/ \u5305\u88c5\u4e86\u91cd\u8bd5\u7684do\u65b9\u6cd5\nfunc (h *HttpSend) HttpDo() []byte {\n    var resp *http.Response\n    var body []byte\n    resp, h.err = h.client.Do(h.request)\n    if h.err == nil {\n        log.Infof(h.ctx, fmt.Sprintf(&quot;HttpDo\uff0cresp:%+v, error:%+v&quot;, resp, h.err))\n        defer resp.Body.Close()\n        if resp.StatusCode == http.StatusOK {\n            body, h.err = ioutil.ReadAll(resp.Body)\n        } else {\n            h.err = errors.New(resp.Status)\n        }\n    } else {\n        for h.doNum &lt; h.tryNum {\n            h.doNum++\n            log.Errorf(h.ctx, fmt.Sprintf(&quot;HttpDo,url:%s,resp:%+v,\u91cd\u8bd5\u6b21\u6570:%d,error:%s&quot;, h.url, resp, h.doNum, h.err))\n            time.Sleep(h.intervalTime)\n            h.NewClient(h.ctx)\n            body = h.HttpDo()\n            return body\n        }\n    }\n    return body\n}\n\n\/\/ \u53d1\u9001get\u8bf7\u6c42\nfunc (h *HttpSend) HttpGet() ([]byte, error) {\n    if h.err != nil {\n        return []byte{}, h.err\n    }\n    defer func(t time.Time) {\n        log.Info(h.ctx, fmt.Sprintf(&quot;took %v\/s&quot;, time.Since(t).Seconds()))\n    }(time.Now())\n    log.Info(h.ctx, fmt.Sprintf(&quot;url:%s,request:%s&quot;, h.url, h.url))\n    h.request, h.err = http.NewRequest(http.MethodGet, h.url, nil)\n    if h.err != nil {\n        return []byte{}, h.err\n    }\n    h.setHeader()\n    var body []byte\n    body = h.HttpDo()\n    log.Infof(h.ctx, fmt.Sprintf(&quot;url:%s,response:%s,error:%s&quot;, h.url, string(body), h.err))\n    return body, h.err\n}\n\n\/\/ \u53d1\u9001json\u53c2\u6570\u7684get\u8bf7\u6c42\nfunc (h *HttpSend) HttpGetWithJson() ([]byte, error) {\n    if h.err != nil {\n        return []byte{}, h.err\n    }\n    getValue, err := json.Marshal(h.getValue)\n    if err != nil {\n        log.Errorf(h.ctx, fmt.Sprintf(&quot;err:%s&quot;, err))\n        return nil, err\n    }\n    log.Infof(h.ctx, fmt.Sprintf(&quot;url:%s,request:%+v&quot;, h.url, h.getValue))\n    h.request, h.err = http.NewRequest(http.MethodGet, h.url, strings.NewReader(string(getValue)))\n    if _, ok := h.header[contentType]; !ok {\n        h.request.Header.Set(contentType, &quot;application\/json&quot;)\n    }\n    h.setHeader()\n    var body []byte\n    body = h.HttpDo()\n    log.Infof(h.ctx, fmt.Sprintf(&quot;url:%s,response:%s,error:%s&quot;, h.url, string(body), h.err))\n    return body, h.err\n}\n\n\/\/ \u53d1\u9001json\u683c\u5f0f\u7684post\u8bf7\u6c42\nfunc (h *HttpSend) HttpPost() ([]byte, error) {\n    if h.err != nil {\n        return []byte{}, h.err\n    }\n    postValue, err := json.Marshal(h.postValue)\n    if err != nil {\n        log.Errorf(h.ctx, fmt.Sprintf(&quot;err:%s&quot;, err))\n        return nil, err\n    }\n    log.Infof(h.ctx, fmt.Sprintf(&quot;url:%s,request:%s&quot;, h.url, h.postValue))\n    h.request, h.err = http.NewRequest(http.MethodPost, h.url, strings.NewReader(string(postValue)))\n    if _, ok := h.header[contentType]; !ok {\n        h.request.Header.Set(contentType, &quot;application\/json&quot;)\n    }\n    h.setHeader()\n    var body []byte\n    body = h.HttpDo()\n    log.Infof(h.ctx, fmt.Sprintf(&quot;url:%s,response:%s&quot;, h.url, string(body)))\n    return body, h.err\n}\n\n\/\/ \u53d1\u9001form-data\u7684post\u8bf7\u6c42\nfunc (h *HttpSend) HttpPostForm() ([]byte, error) {\n    if h.err != nil {\n        return []byte{}, h.err\n    }\n    log.Infof(h.ctx, fmt.Sprintf(&quot;url:%s,postValue:%+v&quot;, h.url, h.postFormValue))\n    h.request, h.err = http.NewRequest(http.MethodPost, h.url, strings.NewReader(h.postFormValue.Encode()))\n    if h.err != nil {\n        return []byte{}, h.err\n    }\n    h.request.Header.Set(contentType, &quot;application\/x-www-form-urlencoded&quot;)\n    var body []byte\n    body = h.HttpDo()\n    log.Infof(h.ctx, fmt.Sprintf(&quot;send post success,body:%s,h.err:%s&quot;, string(body), h.err))\n    return body, h.err\n}\n\n\/\/ \u8bbe\u7f6eheader\nfunc (h *HttpSend) setHeader() {\n    for k, v := range h.header {\n        h.request.Header.Set(k, v)\n    }\n}\n\ntype HttpOptions func(*HttpSend)\n\n\/\/ \u8bbe\u7f6e\u8bf7\u6c42\u8def\u5f84\nfunc UrlOptions(url string) HttpOptions {\n    return func(client *HttpSend) {\n        client.url = url\n    }\n}\n\n\/\/ \u8bbe\u7f6epost\u8bf7\u6c42\u4f53\nfunc PostValueOptions(postValue interface{}) HttpOptions {\n    return func(client *HttpSend) {\n        client.postValue = postValue\n    }\n}\n\n\/\/ \u8bbe\u7f6eform-data\u683c\u5f0f\u7684post\u8bf7\u6c42\u4f53\nfunc PostFormValueOptions(postFormValue url.Values) HttpOptions {\n    return func(client *HttpSend) {\n        client.postFormValue = postFormValue\n    }\n}\n\n\/\/ \u8bbe\u7f6eget\u8bf7\u6c42\u4f53\nfunc GetValueOptions(getValue interface{}) HttpOptions {\n    return func(client *HttpSend) {\n        client.getValue = getValue\n    }\n}\n\n\/\/ \u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4\nfunc TimeOptions(timeout time.Duration) HttpOptions {\n    return func(client *HttpSend) {\n        client.timeout = timeout\n    }\n}\n\n\/\/ \u8bbe\u7f6e\u4ee3\u7406\nfunc ProxyOptions(proxy string) HttpOptions {\n    return func(client *HttpSend) {\n        client.httpProxy = proxy\n    }\n}\n\n\/\/ \u8bbe\u7f6e\u8bf7\u6c42\u5934\nfunc HeaderOptions(header map[string]string) HttpOptions {\n    return func(client *HttpSend) {\n        client.header = header\n    }\n}\n\n\/\/ \u8bbe\u7f6e\u91cd\u8bd5\u53c2\u6570\nfunc TryOptions(tryNum int, intervalTime time.Duration) HttpOptions {\n    return func(client *HttpSend) {\n        client.tryNum = tryNum\n        client.intervalTime = intervalTime\n    }\n}\n<\/code><\/pre>\n<p><strong>\u4f7f\u7528<\/strong><\/p>\n<pre><code class=\"go\">data, err := requests.NewHttpClient(\n        ctx,\n        requests.UrlOptions(xxxUrl),\n        requests.PostValueOptions(postParams),\n        requests.TryOptions(2, time.Second*3)).\n        HttpPost()<\/code><\/pre>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000042738635\">https:\/\/segmentfault.com\/a\/1190000042738635<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5728\u65e5\u5e38\u5f00\u53d1\u4e2d\u7ecf\u5e38\u4f1a\u7528\u5230http\u5e93\u6765\u53d1\u9001\u8bf7\u6c42\uff0c\u5c31\u5c06\u5e38\u7528\u7684\u8bf7\u6c42\u65b9\u6cd5\u5c01\u88c5\u4e86\u4e00\u4e2a\u5e93\uff0c\u7075\u6d3b\u53c8\u597d\u7528\u3002 \u8fd9\u91cc\u7528\u5230\u4e86\u5efa\u9020\u8005\u6a21\u5f0f [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10006789","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006789","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006789"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006789\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006789"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006789"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006789"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}