GET请求

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请求

由于数据在请求体中,根据数据的解析规则,POST有几种Content-Type,具体说明可以阅读 https://blog.csdn.net/raoxiaoya/article/details/106446863

Content-Type常用的两种格式:multipart/form-data, application/x-www-form-urlencoded

1、multipart/form-data
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))

打印信息:

--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf
Content-Disposition: form-data; name="out"; filename="./note.ttt"
Content-Type: application/octet-stream

aaaaaaa
bbbbbbb
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf
Content-Disposition: form-data; name="key"

aaaa
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf
Content-Disposition: form-data; name="id"

123
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf
Content-Disposition: form-data; name="id"

456
--d2b5abf753c3348fb843e24924690a0de3aa487c90eedad8949f713091bf--
2、application/x-www-form-urlencoded

发送普通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
}
3、其他类型

如果要传递的数据是自定义格式的,接收者自定义解析的,比如 json, xml。

text 		=> text/plain
javascript 	=> application/javascript
json 		=> application/json
html 		=> text/html
xml 		=> 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.ClientTimeout
type Client struct {
	Transport RoundTripper
	CheckRedirect func(req *Request, via []*Request) error
	Jar CookieJar
	Timeout time.Duration
}
http 包http.Get(), http.Post()
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
}