Go URL
Go URL
URL简介
URL全称Uniform Resource Location统一资源定位符,用于定位Internet中待访问的文档或资源。
URL提供了一种定位Internet上任意资源的手段,资源可通过各种不同的方案(比如HTTP、FTP、SMTP)来访问,因此URL语法随着方案不同而不同。
URL格式
scheme://[userinfo@]host[:port]/path[?query][#fragment]scheme://[userinfo]@[host]:[port]/path?key1=value1&key2=value2#fragment
格式 | 描述 | ||
scheme | 方案/协议,比如data-id="t31e458f-noUdd7e6" style="height: 30px;"> | host | 主机名或IP地址,用于定位网络位置 |
port | 服务端口 | ||
path | 主机上的资源路径 | ||
query | 查询字符串,使用&连接符链接的键值对。 | ||
fragment | 分段字段 |
URL编码
URL不能有非ASCII字符,非ASCII使用%后跟两位16进制数表示。URL中不能存在空格,空格使用+表示。
字符 | 编码 |
~ | %7 |
Space | %20 |
% | %25 |
net/url
net包对于网络I/O提供了便携式接口,包括TCP/IP、UDP、域名解析、UNIX Socket。尽管net包提供了大量访问底层的接口,但大多数情况下,客户端仅仅只需要最基本的接口。
Golang标准库net/url包
可用于获取URL属性解析URL并实现查询转义
URL解读
URL结构体
type URL struct { Scheme string Opaque string // 编码后的不透明数据 User *Userinfo // 用户名和密码信息 Host string // 主机地址 或 主机:端口 Path string // path (relative paths may omit leading slash) RawPath string // 详细资源地址 ForceQuery bool // append a query ('?') even if RawQuery is empty RawQuery string // 已编码查询字符串 Fragment string // 引用片段可用于表示文档位置 RawFragment string // encoded fragment hint (see EscapedFragment method)}
url.Parse
函数签名
func Parse(rawurl string) (*URL, error)
将原生的rawurl字符串解析转换为URL结构体,进而获取URL的相关属性。原生URL可以是绝对地址,也可以是相对地址。
例如:
rawurl := "postgres://user:pass@host.com:5432/path1/path2/path3?k=v&k1=v1&k2=v2#f"u, err := url.Parse(rawurl)if err != nil { t.Fatal(err)}fmt.Printf("%v\n", u.Scheme) //postgresfmt.Printf("%v\n", u.Opaque)fmt.Printf("%v\n", u.User) //user:passfmt.Printf("%v\n", u.Host) //host.com:5432fmt.Printf("%v\n", u.Path) // /path1/path2/path3fmt.Printf("%v\n", u.RawPath)fmt.Printf("%v\n", u.ForceQuery) //falsefmt.Printf("%v\n", u.RawQuery) //k=v&k1=v1&k2=v2fmt.Printf("%v\n", u.Fragment) //ffmt.Printf("%v\n", u.RawFragment)
URL.Opaque
url.Opaque表示透明类型的URL,即Scheme后没有//的URL。
rawurl := "mailto:coding@gmail.com"u, err := url.Parse(rawurl)if err != nil { panic(err)}fmt.Printf("%v\n", u.Scheme) //mailtofmt.Printf("%v\n", u.Opaque) //coding@gmail.com
URL.User
URL结构体中User字段包含了所有的认证信息url.Userinfo
type Userinfo struct { username string password string passwordSet bool}
通过Userinfo.Username()方法获取username字段值
func (u *Userinfo) Username() string { if u == nil { return "" } return u.username}
通过Userinfo.Password()获取password和passwordSet字段值
func (u *Userinfo) Password() (string, bool) { if u == nil { return "", false } return u.password, u.passwordSet}
例如:
rawurl := "postgres://user:pass@host.com:5432/path1/path2/path3?k=v&k1=v1&k2=v2#f"u, err := url.Parse(rawurl)if err != nil { panic(err)}userinfo := u.Userusername := userinfo.Username()fmt.Printf("%v\n", username) //userpassword, ok := userinfo.Password()if ok { fmt.Printf("%v\n", password) //pass}
URL.Host
url.Host同时包含主机名和端口,若端口存在则需要分割后才能提取。
例如:
rawurl := "postgres://user:pass@host.com:5432/path1/path2/path3?k=v&k1=v1&k2=v2#f"u, err := url.Parse(rawurl)if err != nil { panic(err)}host := u.Hostfmt.Printf("%v\n", host) //host.com:5432//判断是否存在:ok := strings.Contains(host, ":")if ok { h := strings.Split(host, ":") fmt.Printf("%v\n", h) //[host.com 5432] addr := h[0] port := h[1] fmt.Printf("%v\n", addr) //host.com fmt.Printf("%v\n", port) //5432}
url.ParseRequestURI
url.ParseRequestURI解析原生URL为一个URL结构体
url.ParseRequestURI原生URL是一个绝对URL或绝对路径
url.ParseRequestURI会忽略URL中的fragment分片参数
例如:
rawurl := "err := url.ParseRequestURI(rawurl)if err != nil { t.Fatal(err)}t.Logf("url.Scheme: %v\f", u.Scheme) //url.Scheme: %v\f", u.Host) //url.Host: baidu.comt.Logf("url.Path: %v\f", u.Path) //url.Path: /searcht.Logf("url.RawQuery: %v\f", u.RawQuery) //url.RawQuery: q=dotnet
url.PathEscape
URL中不允许存在空格和非ASCII字符,如果URL的资源路径path字符串中存在空格和ASCII字符则可采用url.PathEscape将非ASCII字符转义为使用%后跟2位16进制数的形式,采用PathUnescape方法解码还原为原始模式。
func PathEscape(s string) string
PathEscape将路径字符串转义,以便将其安全地放置在URL路径段中。
func PathUnescape(s string) (string, error)
PathUnescape执行与PathEscape的逆转换PathUnescape和QueryUnescape相同,只是PathUnescape不会将+加号转换为空格。
例如:
rawurl := "理 员&pid=0#footer"encodeurl := url.PathEscape(rawurl)t.Log(encodeurl)
err := url.PathUnescape(encodeurl)if err != nil { t.Fatal(err)}t.Log(decodeurl)
理 员&pid=0#footer
转义前 | 转义后 |
/ | %2F |
? | %3F |
# | %23 |
空格 | %20 |
PathEscape会将空格转换为%20PathEscape不会对URL中的:和&进行转义编码
url.QueryEscape
对URL的查询字符串进行编码和解码QueryEscape将URL中的查询字符串转义,以便安全地放置到URL查询字符串中。
URL中不允许存在空格和非ASCII字符,如果URL的查询字符串query字符串中存在空格和ASCII字符则可采用url.QueryEscape将非ASCII字符转化为使用%后跟2位16进制数的形式,采用QueryUnescape方法解码还原为原始模式。
func QueryEscape(s string) string
例如:
rawurl := "理 员&pid=0#footer"encodeurl := url.QueryEscape(rawurl)t.Log(encodeurl)
QueryUnescape(s string) (string, error)
例如:
rawurl := "理 员&pid=0#footer"encodeurl := url.QueryEscape(rawurl)decodeurl, err := url.QueryUnescape(encodeurl)if err != nil { t.Fatal(err)}t.Log(decodeurl)
理 员&pid=0#footer
转义前 | 转义后 |
: | %3A |
/ | %2F |
? | %3F |
& | %26 |
# | %23 |
空格 | + |
QueryEscape会将空格转换为+加号QueryEscape会将/路径分隔符转换为%2F
url.ParseQuery
func ParseQuery(query string) (Values, error) { m := make(Values) err := parseQuery(m, query) return m, err}
URL中的查询字符串可采用url.ParseQuery解析生成一个url.Values字典实例。
例如:
rawurl := "err := url.Parse(rawurl)if err != nil { panic(err)}query := u.RawQueryfmt.Printf("%v\n", query) //id=1&name=admin&pid=0values, err := url.ParseQuery(query)if err != nil { panic(err)}fmt.Printf("%v\n", values) //map[id:[1] name:[admin] pid:[0]]fmt.Printf("%v\n", values["id"][0]) //1fmt.Printf("%v\n", values["name"][0]) //adminfmt.Printf("%v\n", values["pid"][0]) //0
封装:从URL的查询字符串中通过键获得值
func GetQueryStringField(rawurl string, key string) (string, error) { u, err := url.Parse(rawurl) if err != nil { return "", err } query := u.RawQuery values, err := url.ParseQuery(query) if err != nil { return "", err } value := values.Get(key) return value, nil}
rawurl := "err := GetQueryStringField(rawurl, "id")if err != nil { panic(err)}fmt.Printf("%v\n", id) //1
url.Query
func (u *URL) Query() Values { v, _ := ParseQuery(u.RawQuery) return v}
rawurl := "err := url.Parse(rawurl)if err != nil { panic(err)}values := u.Query()fmt.Printf("%v\n", values) //map[id:[1] name:[admin] pid:[0]]id := values.Get("id")fmt.Printf("%v\n", id) //1
重置查询字符串键值对
rawurl := "err := url.Parse(rawurl)if err != nil { panic(err)}values := u.Query()values.Set("id", "100")u.RawQuery = values.Encode()t.Log(u) //Values map[string][]stringfunc (v Values) Get(key string) stringfunc (v Values) Set(key, value string)func (v Values) Add(key, value string)func (v Values) Del(key string)func (v Values) Encode() string
将url.Values转换为查询字符串
func BuildHTTPQueryString(values url.Values) string { var keys []string for k := range values { keys = append(keys, k) } sort.Strings(keys) bb := bytes.Buffer{} for _, key := range keys { val := values.Get(key) bb.WriteString(key) bb.WriteString("=") bb.WriteString(val) bb.WriteString("&") } return strings.TrimRight(bb.String(), "&")}
values := url.Values{}values.Add("id", "1")values.Add("name", "admin")values.Add("pid", "0")queryString := BuildHTTPQueryString(values)fmt.Printf("%v\n", queryString) //id=1&name=admin&pid=0
values.Encode
例如:HTTP请求将URL传递过来的参数编码为以&连接的字符串
values := url.Values{}values.Add("app_id", "2016073100129537")values.Add("out_trade_no", "2201010101")values.Add("method", "alipay.trade.app.pay")values.Add("notify_url", ""2017-11-10 17:54:34")values.Add("sign_type", "RSA2")values.Add("version", "1.0")encode := values.Encode()fmt.Printf("%v\n", encode)
app_id=2016073100129537&method=alipay.trade.app.pay¬ify_url=http%3A%2F%2F203.86.24.181%3A3000%2Falipay&out_trade_no=2201010101&sign_type=RSA2×tamp=2017-11-10+17%3A54%3A34&version=1.0
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~