Go URL

URL简介

URL全称Uniform Resource Location统一资源定位符,用于定位Internet中待访问的文档或资源。

URL提供了一种定位Internet上任意资源的手段,资源可通过各种不同的方案(比如HTTP、FTP、SMTP)来访问,因此URL语法随着方案不同而不同。

<schema>://<user>:<password>@<host>:<port>/<path>:<params>?<query>#<frag>URL格式scheme://[userinfo@]host[:port]/path[?query][#fragment]scheme://[userinfo]@[host]:[port]/path?key1=value1&key2=value2#fragment

格式

描述

scheme

方案/协议,比如http、https、ftp、file…

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.comURL.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 := “http://www.baidu.com/search?q=dotnet”u, err := url.ParseRequestURI(rawurl)if err != nil { t.Fatal(err)}t.Logf(“url.Scheme: %v\f”, u.Scheme) //url.Scheme: httpt.Logf(“url.Host: %v\f”, u.Host) //url.Host: www.baidu.comt.Logf(“url.Path: %v\f”, u.Path) //url.Path: /searcht.Logf(“url.RawQuery: %v\f”, u.RawQuery) //url.RawQuery: q=dotneturl.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 := “http://www.baidu.com/search?id=1&name=管 理 员&pid=0#footer”encodeurl := url.PathEscape(rawurl)t.Log(encodeurl)http:%2F%2Fwww.baidu.com%2Fsearch%3Fid=1&name=%E7%AE%A1%20%E7%90%86%20%E5%91%98&pid=0%23footerdecodeurl, err := url.PathUnescape(encodeurl)if err != nil { t.Fatal(err)}t.Log(decodeurl)http://www.baidu.com/search?id=1&name=管 理 员&pid=0#footer

转义前

转义后

/

%2F

?

%3F

#

%23

空格

%20

PathEscape会将空格转换为??%20??PathEscape不会对URL中的??:???和??&??进行转义编码url.QueryEscape对URL的查询字符串进行编码和解码QueryEscape将URL中的查询字符串转义,以便安全地放置到URL查询字符串中。

URL中不允许存在空格和非ASCII字符,如果URL的查询字符串??query???字符串中存在空格和ASCII字符则可采用??url.QueryEscape???将非ASCII字符转化为使用??%???后跟2位16进制数的形式,采用??QueryUnescape??方法解码还原为原始模式。

func QueryEscape(s string) string

例如:

rawurl := “http://www.baidu.com/search?id=1&name=管 理 员&pid=0#footer”encodeurl := url.QueryEscape(rawurl)t.Log(encodeurl)http%3A%2F%2Fwww.baidu.com%2Fsearch%3Fid%3D1%26name%3D%E7%AE%A1+%E7%90%86+%E5%91%98%26pid%3D0%23footerQueryUnescape执行与QueryEscape的逆转换func QueryUnescape(s string) (string, error)

例如:

rawurl := “http://www.baidu.com/search?id=1&name=管 理 员&pid=0#footer”encodeurl := url.QueryEscape(rawurl)decodeurl, err := url.QueryUnescape(encodeurl)if err != nil { t.Fatal(err)}t.Log(decodeurl)http://www.baidu.com/search?id=1&name=管 理 员&pid=0#footer

转义前

转义后

:

%3A

/

%2F

?

%3F

&

%26

#

%23

空格

+

QueryEscape会将空格转换为??+??加号QueryEscape会将??/???路径分隔符转换为??%2F??url.ParseQueryfunc ParseQuery(query string) (Values, error) { m := make(Values) err := parseQuery(m, query) return m, err}

URL中的查询字符串可采用??url.ParseQuery???解析生成一个??url.Values??字典实例。

例如:

rawurl := “http://www.baidu.com/search?id=1&name=admin&pid=0#footer”u, 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 := “http://www.baidu.com/search?id=1&name=admin&pid=0#footer”id, err := GetQueryStringField(rawurl, “id”)if err != nil { panic(err)}fmt.Printf(“%v\n”, id) //1url.Queryfunc (u *URL) Query() Values { v, _ := ParseQuery(u.RawQuery) return v}rawurl := “http://www.baidu.com/search?id=1&name=admin&pid=0#footer”u, 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 := “http://www.baidu.com/search?id=1&name=admin&pid=0#footer”u, err := url.Parse(rawurl)if err != nil { panic(err)}values := u.Query()values.Set(“id”, “100”)u.RawQuery = values.Encode()t.Log(u) //http://www.baidu.com/search?id=100&name=admin&pid=0#footerurl.Valuestype 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=0values.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”, “http://203.86.24.181:3000/alipay”)values.Add(“timestamp”, “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

【本文来源:香港服务器租用 st.html欢迎留下您的宝贵建议】每个人在他的人生发轫之初,总有一段时光,

Go URL

相关文章:

你感兴趣的文章:

标签云: