Go Web:URLs
URL也是一個結構體:
type URL struct {Scheme stringOpaque string // encoded opaque dataUser *Userinfo // username and password informationHost string // host or host:portPath string // path (relative paths may omit leading slash)RawPath string // encoded path hint (see EscapedPath method)ForceQuery bool // append a query ('?') even if RawQuery is emptyRawQuery string // encoded query values, without '?'Fragment string // fragment for references, without '#' }URL結構表示解析之后的URL,一般格式為:
[scheme:][//[userinfo@]host][/]path[?query][#fragment]由于path和query部分只能使用大小寫字母、數字以及有限的幾個特殊標點,其它所有的字符都需要進行URL編碼:百分號+2位16進制數。例如,空格被編碼為"%20",斜線被編碼為"%2f",有時候query的value中空格會被編碼為"+"。
例如,query部分被編碼后的內容如下:
name=Hiram%20Veeblefeetzer&age=35&country=Madagascar+abc它表示3個key/value:name="Hiram Veeblefeetzer"、age=35、country=Madagascar abc。
關于URL,其中:
- Host字段是包含host和port兩部分的,如果需要分別返回host、port,使用URL.Hostname、URL.Port
- User字段包含了Username和Password,要分別返回它們,使用URL.User.Username(),URL.User.Password()
- Path字段表示解碼后的URL路徑,也就是不帶"%"的普通字符串路徑
- RawPaht字段表示編碼后的安全路徑,即帶上了"%"的路徑
- RawQuery字段表示編碼后的Query,即打上了"%"的query字符串,它包含了所有key/value,要分離每個key/value,使用ParseQuery()方法將它們解析到一個map中
URL解析示例
使用URL的Parse(string)方法可以將字符串構造成一個URL對象,并返回這個URL對象的指針。
現在使用這個方法來構造一個URL對象,并解析其中的各個部分:
package mainimport "fmt" import "net/url"func main() {// 將字符串構造成URL對象s := "postgres://user:pass@host.com:5432/path?k=v#f"u, err := url.Parse(s)if err != nil {panic(err)}// 獲取schema部分fmt.Println(u.Scheme)// User字段包含了Username和Password,需要分別獲取fmt.Println(u.User)fmt.Println(u.User.Username())p, _ := u.User.Password()fmt.Println(p)// Host字段包含了hostname和portfmt.Println(u.Host)fmt.Println(u.Hostname())fmt.Println(u.Port())// 取得Path和Fragment字段fmt.Println(u.Path)fmt.Println(u.Fragment)// 取得query的key/value// 要取出各個key/value,使用ParseQuery()將RawQuery字段解析成map// key是字符串,value是字符串的slice,如果有key相同,則多個值放進這個slicefmt.Println(u.RawQuery)m, _ := url.ParseQuery(u.RawQuery)fmt.Println(m)fmt.Println(m["k"][0]) }結果:
postgres user:pass user pass host.com:5432 host.com 5432 /path f k=v map[k:[v]] v構造URL
URL的Parse(string)方法可以將字符串構造成一個URL對象,URL的String()方法可以返回編碼后的URL值。
例如:
urlstr := "http://www.cnblogs.com/f-ck-need-u" myurl,_ := url.Parse(urlstr) fmt.Println(myurl.String())輸出:
http://www.cnblogs.com/f-ck-need-u由于URL的path和query部分可能包含特殊字符,直接使用純字符串構造URL會不安全。應該使用另外兩個函數將普通字符轉換成編碼后的字符:
func PathEscape(s string) string func QueryEscape(s string) string再將編碼之后的path和query作為Parse()方法的一部分。
例如:
package mainimport ("fmt""net/url" )func main() {// 要構造:http://www.example.int/下// Path: search// Query: food=pie aaa// action=like// 的URLs := "http://www.example.int"p := "search"path := url.PathEscape(p)// query部分qfood := "pie aaa"qaction := "like"qqfood := url.QueryEscape(qfood)qqaction := url.QueryEscape(qaction)// 將query組合起來query := "food=" + qqfood + "&action=" + qqaction// 構造urlmyurlstr := s + "/" + path + "?" + querymyurl, err := url.Parse(myurlstr)if err != nil {panic(err)}// 解析URLfmt.Println(myurl.String())// 解析url的query部分fmt.Println(myurl.RawQuery)qmaps, _ := url.ParseQuery(myurl.RawQuery)fmt.Println(qmaps["food"])fmt.Println(qmaps["action"]) }這很麻煩,對于Query部分,更好的方法是使用Values.Encode()方法,見后文。
url Path部分
在URL結構中:有Path和RawPath兩個字段
type URL struct{...Path string // path (relative paths may omit leading slash)RawPath string // encoded path hint (see EscapedPath method)... }其中Path是解碼后的路徑,RawPath是編碼后的路徑。
前面解釋了PathEscape()函數,它是將字符串轉換為編碼后的字符串,可以直接將編碼后的結果作為構造url的path部分,這樣是最安全的構造方式。
除此之外,還有一個EscapePath()方法:如果RawPath存在且有效,則直接返回RawPath字段的值,如果不存在,則EscapePath()自己計算一個編碼后的路徑。
URL.String()方法是直接調用EscapePath()來構造路徑部分的。
Userinfo
type Userinfofunc User(username string) *Userinfofunc UserPassword(username, password string) *Userinfofunc (u *Userinfo) Password() (string, bool)func (u *Userinfo) String() stringfunc (u *Userinfo) Username() stringUser()函數構造一個Userinfo,但只包含Username不包含password。
UserPassword()函數構造一個Userinfo,包含Username和password,但因為明文顯示,不建議使用。
String()返回"username[:password]"格式的username和Password。
Username()和Password()分別返回對應的部分。
Query部分
URL結構中有一個RawQuery字段:
type URL struct {...RawQuery string... }RawQuery字段是編碼后的query。
有幾個方法:
func (u *URL) Query() Values它讀取RawQuery字段的值并返回Values類型。但會直接丟棄錯誤或畸形的query部分,如果要檢查錯誤或畸形,使用ParseQuery()函數。
注意上面Query()的返回值是Values類型,它是一個map結構:
type Values map[string][]stringfunc ParseQuery(query string) (Values, error)func (v Values) Add(key, value string)func (v Values) Del(key string)func (v Values) Encode() stringfunc (v Values) Get(key string) stringfunc (v Values) Set(key, value string)ParseQuery()函數解析給定字符串query并將query的各個部分填充到返回值類型Values的map結構中,同時會檢查錯誤。
Add()、Del()、Set()和Get()都用來操作Values的map結構,意義都很清晰。唯一需要注意的是,Add()是追加操作,Set()是替換已有值,如果操作的key不存在,則直接創建。
Encode()是將Values中的數據根據key排序后編碼成URL的query,且是編碼后的query。
下面是一個用法:
package mainimport ("fmt""net/url" )func main() {s := "http://www.example.int"p := "search"path := url.PathEscape(p)// query部分values := url.Values{}values.Set("food","pie aaa")values.Add("action","like")values.Add("name","abc")values.Add("name","def")values.Add("name","gh")// Encode() == "action=like&food=pie+aaa&name=abc&name=def&name=gh"query := values.Encode()// 構造urlmyurlstr := s + "/" + path + "?" + querymyurl, err := url.Parse(myurlstr)if err != nil {panic(err)}// 解析urlfmt.Println(myurl.String()) }轉載于:https://www.cnblogs.com/f-ck-need-u/p/10020927.html
總結
以上是生活随笔為你收集整理的Go Web:URLs的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 常用机器学习算法
- 下一篇: 使用Redis实现分布式锁