go http请求如果参数中带有"等特殊字符,参数传输可能会出现问题,所以传输前需要进行参数编码。
在 Golang 中有 net/url
包是用来专门处理 URL 的, net/url
包有完整的URL解析函数,编码函数,解编码函数。
解析 URL 可以使用 url.Parse()
函数。这个函数功能类似于 PHP 下的 parse_url()
函数。
import (
"fmt"
"github.com/liudng/godump"
"net/url"
)
urlStr := "https://cong5.net/post/golang?name=张三&age=20&sex=1"
parseUrl,_ := url.Parse(urlStr)
URL 解析后,我们来看一下返回的数据结构:
(*url.URL)
(url.URL)
Scheme(string) "https"
Opaque(string) ""
User(*url.Userinfo)
User(string) ""
Host(string) "www.example.com"
Path(string) "/index.php"
RawPath(string) ""
ForceQuery(bool) false
RawQuery(string) "name=张三&age=20&sex=1"
Fragment(string) ""
要获取里面的某个值,可以这样直接获取:
fmt.Println("Scheme:" + parseUrl.Scheme)
fmt.Println("Host: " + parseUrl.Host) //还有 parseUrl.Hostname() 也是获取主机名
fmt.Println("Path: " + parseUrl.Path)
fmt.Println("RawQuery:" + parseUrl.RawQuery)
//输出
//Scheme:https
//Host: cong5.net
//Path: /post/golang
//RawQuery:name=张三&age=20&sex=1
通过上面的操作返回的对象,我们发现回去到的 Query 参数是一个字符串,没有解析。 如果我们想获取 Query 参数呢?在PHP中我们可以使用 parse_str()
函数解析成数组。
query := parseUrl.Query()
fmt.Println("name:" + query.Get("name"))
fmt.Println("age:" + query.Get("age"))
fmt.Println("sex:" + query.Get("sex"))
//name:张三
//age:20
//sex:1
如果我们要对完整的 URL 进行编码呢? 就是PHP中 urlencode()
函数的功能。 在 GO 语言下可以直接使用 url.QueryEscape()
函数。
escapeUrl := url.QueryEscape(urlStr)
fmt.Println(escapeUrl)
/**
输出:https%3A%2F%2Fcong5.net%2Fpost%2Fgolang%3Fname%3D%E5%BC%A0%E4%B8%89%26age%3D20%26sex%3D1
**/
既然有了编码,那么就肯定有配套的解编码函数的了。 PHP中有 urldecode()
函数的功能。 在GO 语言下可以直接使用 url.QueryUnescape()
函数。
enEscapeUrl, _ := url.QueryUnescape(escapeUrl)
fmt.Println(enEscapeUrl)
//输出:
//https://cong5.net/post/golang?name=张三&age=20&sex=1
有了解析,编码、解码的函数了。那么我们可能还想到一个 PHP 下的函数 http_build_query()
,这个函数可以自动拼接生成URL参数字符串的功能。 在 GO 语言下同样可以,在 GO 语言中获取 Query()
实例,然后有 GET/SET/ADD/DEL
方法对参数进行获取,增加,删除,修改等操作。
var urlS url.URL
q := urlS.Query()
q.Add("name", "张三")
q.Add("age", "20")
q.Add("sex", "1")
queryStr := q.Encode()
fmt.Println(queryStr)
//输出:
//age=20&name=%E5%BC%A0%E4%B8%89&sex=1
var urlS url.URL
q := urlS.Query()
q.Add("query", quey)
q.Add("time", fmt.Sprintf("%v", time))
params := q.Encode()
//params := fmt.Sprintf("query=%v&time=%v", query, time)
req, _ := http.NewRequest("GET", "http://xxx", nil)
req.URL = &url.URL{
Scheme: req.URL.Scheme,
Host: req.URL.Host,
RawQuery: params,
Path: "/api/v1/query",
}
req.URL.EscapedPath()
resp, e := http.Get(req.URL.String())
if e != nil {
errMsg := fmt.Sprintf("fail:%v,%v", resp, e)
return errMsg
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
errMsg := fmt.Sprintf("parse resp from resp.body fail:%v,%v", resp.Body, err)
return errMsg
}
logs.Info("debug response %v", string(body))
if err := json.Unmarshal(body, &reData); err != nil {
errMsg := fmt.Sprintf("fail:%v,%v", string(body), err)
return reData, errors.New(errMsg)
}
return errMsg
}