本文共 6703 字,大约阅读时间需要 22 分钟。
func CurlGetWithParam(link string, param map[string]string) (response string, err error) { u, _ := url.Parse(link) q := u.Query() for k, val := range param { q.Set(k, val) } u.RawQuery = q.Encode() link = u.String() resp, err := http.Get(link) if err != nil { return response, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) return string(body), nil}
由于数据在请求体中,根据数据的解析规则,POST有几种Content-Type,具体说明可以阅读 https://blog.csdn.net/raoxiaoya/article/details/106446863
Content-Type常用的两种格式:multipart/form-data, application/x-www-form-urlencoded
可以上传文件,数据以boundary分割,类似于 multipart/form-data; boundary---------------xxxxxxxxxx
func CurlPostWithParam4(link string, param map[string][]string, header map[string]string, files map[string]string) (response string, err error) { data := &bytes.Buffer{ } writer := multipart.NewWriter(data) // 处理文件内容 for name, path := range files { part, err := writer.CreateFormFile(name, path) if err != nil { return response, err } f, err := os.Open(path) if err != nil { return response, err } _, err = io.Copy(part, f) if err != nil { return response, err } } // 处理其他字段 for k, sli := range param { for _, s := range sli { writer.WriteField(k, s) } } err = writer.Close() if err != nil { return response, err } // 查看数据流 // p, _ := ioutil.ReadAll(data) // fmt.Println(string(p)) req, err := http.NewRequest("POST", link, data) if err != nil { return response, err } // 处理header for k, v := range header { req.Header.Set(k, v) } // **** 重要 req.Header.Set("Content-Type", writer.FormDataContentType()) client := &http.Client{ } resp, err := client.Do(req) if err != nil { return response, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) return string(body), nil}
本函数支持header, 文件,切片value
func main() { p4 := map[string][]string{ "key": { "aaaa"}, "id": { "123", "456"}} file := map[string]string{ "out": "./note.ttt"} rep4, err := CurlPostWithParam4("http://192.168.2.157:8000/vote2/Vote", p4, nil, file) fmt.Println(rep4) fmt.Println(err)}
查看打印数据流
p, _ := ioutil.ReadAll(data)fmt.Println(string(p))
打印信息:
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bfContent-Disposition: form-data; name="out"; filename="./note.ttt"Content-Type: application/octet-streamaaaaaaabbbbbbb--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bfContent-Disposition: form-data; name="key"aaaa--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bfContent-Disposition: form-data; name="id"123--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bfContent-Disposition: form-data; name="id"456--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf--
发送普通key-value,以&拼接。
func CurlPostWithParam1(link string, param map[string]string) (response string, err error) { str := "" for k, val := range param { if str == "" { str = k + "=" + val } else { str = str + "&" + k + "=" + val } } r := strings.NewReader(str) resp, err := http.Post(link, "application/x-www-form-urlencoded", r) if err != nil { return response, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) return string(body), nil}
发送的value是一个切片,也就是可以发送数组。
func CurlPostWithParam2(link string, param map[string][]string) (response string, err error) { // fmt.Println(url.Values(param).Encode()) // id=123&key=Value&key=aaaa resp, err := http.PostForm(link, url.Values(param)) if err != nil { return response, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) return string(body), nil}
带请求头的
func CurlPostWithParam3(link string, param map[string][]string, header map[string]string) (response string, err error) { r := strings.NewReader(url.Values(param).Encode()) req, err := http.NewRequest("POST", link, r) if err != nil { return response, err } for k, v := range header { req.Header.Set(k, v) } client := &http.Client{ } resp, err := client.Do(req) if err != nil { return response, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) return string(body), nil}
如果要传递的数据是自定义格式的,接收者自定义解析的,比如 json, xml。
text => text/plainjavascript => application/javascriptjson => application/jsonhtml => text/htmlxml => application/xml
可通过设置 req.Header.Set(“Content-Type”, “application/json”)
func CurlPostWithParam5(link string, param string, header map[string]string) (response string, err error) { r := strings.NewReader(param) req, err := http.NewRequest("POST", link, r) if err != nil { return response, err } for k, v := range header { req.Header.Set(k, v) } req.Header.Set("Content-Type", "application/json") client := &http.Client{ } resp, err := client.Do(req) if err != nil { return response, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) return string(body), nil}
超时设置是在 http.Client
对象里面的 Timeout
字段
type Client struct { Transport RoundTripper CheckRedirect func(req *Request, via []*Request) error Jar CookieJar Timeout time.Duration}
http 包
下的快捷方式,如 http.Get(), http.Post()
使用的是默认的client,因此 Timeout 为零值,就是 0 ,也就是不超时。
func Get(url string) (resp *Response, err error) { return DefaultClient.Get(url)}var DefaultClient = &Client{ }
所以,想要设置超时,需要使用自定义的client来发起请求,类似于。
c := http.Client{ Timeout: time.Second * 2,}req, err := http.NewRequest("GET", "http://192.168.2.157:8001/common/GetOpenidByCode?code=xxxx", strings.NewReader(""))if err != nil { panic(err)}resp, err := c.Do(req)if err != nil { panic(err)}defer resp.Body.Close()body, err := ioutil.ReadAll(resp.Body)fmt.Println(string(body))fmt.Println(err)
综合一下
func CurlWithParam(link string, method string, param map[string]string) (response string, err error) { client := http.Client{ Timeout: time.Second * 10} m := strings.ToLower(method) var resp *http.Response if m == "get" { u, _ := url.Parse(link) q := u.Query() for k, val := range param { q.Set(k, val) } u.RawQuery = q.Encode() link = u.String() resp, err = client.Get(link) } else if m == "post" { str := "" for k, val := range param { if str == "" { str = k + "=" + val } else { str = str + "&" + k + "=" + val } } r := strings.NewReader(str) client := http.Client{ Timeout: time.Second * 10} resp, err = client.Post(link, "application/x-www-form-urlencoded", r) } else { return response, errors.New("only support get and post method") } if err != nil { return response, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) return string(body), nil}