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
根据Content-Type,接收者就可以解析数据了。
boundary后面的字符串是随机生成的。
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--
发送普通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/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.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
}