Go 学习笔记(50)— Go 标准库之 net/url(查询转义、查询参数增/删/改/查、解析URL)
1. URL 概述
import "net/url"
url 包解析 URL 并實(shí)現(xiàn)了查詢的轉(zhuǎn)碼。URL 提供了一種定位因特網(wǎng)上任意資源的手段,但這些資源是可以通過(guò)各種不同的方案(比如 HTTP 、 FTP 、 SMTP )來(lái)訪問,因此 URL 語(yǔ)法會(huì)隨著方案的不同而不同。
完整的 URL 格式為:
<schema>://<user>:<password>@<host>:<port>/<path>:<params>?<query>#<frag>
各部分字段說(shuō)明:
scheme: 方案是如何訪問指定資源的主要標(biāo)識(shí)符,他會(huì)告訴負(fù)責(zé)解析URL應(yīng)用程序應(yīng)該使用什么協(xié)議;user:用戶名;password:密碼;host: 主機(jī)組件標(biāo)識(shí)了因特網(wǎng)上能夠訪問資源的宿主機(jī)器,可以有主機(jī)名或者是IP地址來(lái)表示;port: 端口標(biāo)識(shí)了服務(wù)器正在監(jiān)聽的網(wǎng)絡(luò)端口。默認(rèn)端口號(hào)是 80;path:URL的路徑組件說(shuō)明了資源位于服務(wù)器的什么地方;params:URL中通過(guò)協(xié)議參數(shù)來(lái)訪問資源,比名值對(duì)列表,分號(hào)分割來(lái)進(jìn)行訪問;query: 字符串是通過(guò)提問問題或進(jìn)行查詢來(lái)縮小請(qǐng)求資源類的范圍;frag: 為了引用部分資源或資源的一個(gè)片段,比如URL指定HTML文檔中一個(gè)圖片或一個(gè)小節(jié);
HTTP 通常只處理整個(gè)對(duì)象,而不是對(duì)象的片段,客戶端不能將片段傳送給服務(wù)器。瀏覽器從服務(wù)器獲取整個(gè)資源之后,會(huì)根據(jù)片段來(lái)顯示你感興趣的片段部分。
2. 主要類型和函數(shù)
2.1 type URL
Go 中 URL 結(jié)構(gòu)體如下:
type URL struct {Scheme string //具體指訪問服務(wù)器上的資源使用的哪種協(xié)議Opaque string // 編碼后的不透明數(shù)據(jù)User *Userinfo // 用戶名和密碼信息,有些協(xié)議需要傳入明文用戶名和密碼來(lái)獲取資源,比如 FTPHost string // host或host:port,服務(wù)器地址,可以是 IP 地址,也可以是域名信息Path string //路徑,使用"/"分隔RawPath string // 已編碼的路徑提示(參見EscapedPath方法)ForceQuery bool // 添加一個(gè)查詢('?'),即使RawQuery為空RawQuery string // 編碼后的查詢字符串,沒有'?'Fragment string // 引用的片段(文檔位置),沒有'#'
}
示例代碼:
func main() {urlString := "https://admin:passwd@www.baidu.com:80/search?mq=test#12345"u, err := url.Parse(urlString)if err != nil {fmt.Println("parse error ", err)}fmt.Printf("u type is %T, u is %#v\n", u, u)/*u type is *url.URL,u is &url.URL{Scheme:"https", Opaque:"", User:(*url.Userinfo)(0xc000088150),Host:"www.baidu.com:80", Path:"/search", RawPath:"", ForceQuery:false,RawQuery:"mq=test", Fragment:"12345"}*/fmt.Printf("u.Scheme is %#v\n", u.Scheme) // u.Scheme is "https"fmt.Printf("u.Opaque is %#v\n", u.Opaque) // u.Opaque is ""fmt.Printf("u.User is %#v\n", u.User)// u.User is &url.Userinfo{username:"admin", password:"passwd", passwordSet:true}fmt.Printf("u.Host is %#v\n", u.Host) // u.Host is "www.baidu.com:80"fmt.Printf("u.Path is %#v\n", u.Path) // u.Path is "/search"fmt.Printf("u.RawPath is %#v\n", u.RawPath) // u.RawPath is ""fmt.Printf("u.ForceQuery is %#v\n", u.ForceQuery) // u.ForceQuery is falsefmt.Printf("u.RawQuery is %#v\n", u.RawQuery) // u.RawQuery is "mq=test"fmt.Printf("u.Fragment is %#v\n", u.Fragment) // u.Fragment is "12345"}
2.1.1 func Parse
func Parse(rawurl string) (url *URL, err error)
Parse 函數(shù)解析rawurl為一個(gè)URL結(jié)構(gòu)體,rawurl` 可以是絕對(duì)地址,也可以是相對(duì)地址。
2.1.2 func ParseRequestURI
func ParseRequestURI(rawurl string) (url *URL, err error)
ParseRequestURI 函數(shù)解析 rawurl 為一個(gè) URL 結(jié)構(gòu)體,本函數(shù)會(huì)假設(shè) rawurl 是在一個(gè) HTTP 請(qǐng)求里,因此會(huì)假設(shè)該參數(shù)是一個(gè)絕對(duì) URL 或者絕對(duì)路徑,并會(huì)假設(shè)該 URL 沒有 #fragment 后綴。(網(wǎng)頁(yè)瀏覽器會(huì)在去掉該后綴后才將網(wǎng)址發(fā)送到網(wǎng)頁(yè)服務(wù)器)
func main() {urlString := "https://admin:passwd@www.baidu.com:80/search?mq=test#12345"u, err := url.ParseRequestURI(urlString)if err != nil {fmt.Println("parse error ", err)}fmt.Printf("u.Fragment is %#v\n", u.Fragment) // u.Fragment is ""}
2.1.3 func (*URL) IsAbs
func (u *URL) IsAbs() bool
函數(shù)在 URL 是絕對(duì) URL 時(shí)才返回真。
2.1.4 func (*URL) Query
func (u *URL) Query() Values
Query 方法解析 RawQuery 字段并返回其表示的 Values 類型鍵值對(duì)。
2.1.5 func (*URL) RequestURI
func (u *URL) RequestURI() string
RequestURI 方法返回編碼好的 path?query 或 opaque?query 字符串,用在 HTTP 請(qǐng)求里。
2.1.6 func (*URL) String
func (u *URL) String() string
String 將 URL 重構(gòu)為一個(gè)合法 URL 字符串。
2.1.7 func (*URL) Parse
func (u *URL) Parse(ref string) (*URL, error)
Parse 方法以 u 為上下文來(lái)解析一個(gè) URL , ref 可以是絕對(duì)或相對(duì) URL 。本方法解析失敗會(huì)返回 nil , err ;否則返回結(jié)果和 ResolveReference 一致。
func main() {u, _ := url.Parse("http://example.com/dir/")fmt.Println(u) // http://example.com/dir/result, _ := u.Parse("./search?mq=rabbitmq")fmt.Println(result) // http://example.com/dir/search?mq=rabbitmq
}
2.1.8 func (*URL) ResolveReference
func (u *URL) ResolveReference(ref *URL) *URL
本方法根據(jù)一個(gè)絕對(duì) URI 將一個(gè) URI 補(bǔ)全為一個(gè)絕對(duì) URI 。參數(shù) ref 可以是絕對(duì) URI 或者相對(duì) URI 。 ResolveReference 總是返回一個(gè)新的 URL 實(shí)例,即使該實(shí)例和 u 或者 ref 完全一樣。如果 ref 是絕對(duì) URI ,本方法會(huì)忽略參照 URI 并返回 ref 的一個(gè)拷貝。
2.1.9 代碼示例
func main() {urlString := "https://www.baidu.com/search?mq=rabbitmq&queue=people#12345"u, err := url.Parse(urlString)if err != nil {fmt.Println("parse error ", err)}fmt.Printf("u.IsAbs is %#v\n", u.IsAbs()) // u.IsAbs is truefmt.Printf("u.Query is %#v\n", u.Query())// u.Query is url.Values{"mq":[]string{"rabbitmq"}, "queue":[]string{"people"}}fmt.Printf("u.RequestURI is %#v\n", u.RequestURI())// u.RequestURI is "/search?mq=rabbitmq&queue=people"fmt.Printf("u.String is %#v\n", u.String())// u.String is "https://www.baidu.com/search?mq=rabbitmq&queue=people#12345"}
2.2 type Values
type Values map[string][]string
Values 將建映射到值的列表。它一般用于查詢的參數(shù)和表單的屬性。不同于 http.Header 這個(gè)字典類型, Values 的鍵是大小寫敏感的。
2.2.1 func ParseQuery
func ParseQuery(query string) (m Values, err error)
ParseQuery 函數(shù)解析一個(gè) URL 編碼的查詢字符串,并返回可以表示該查詢的 Values 類型的字典。本函數(shù)總是返回一個(gè)包含了所有合法查詢參數(shù)的非 nil 字典, err 用來(lái)描述解碼時(shí)遇到的(如果有)第一個(gè)錯(cuò)誤。
代碼示例:
func main() {rawUrl := "mq=rabbitmq&queue=people"v, err := url.ParseQuery(rawUrl)if err != nil {fmt.Println("ParseQuery error ", err)}fmt.Printf("v type is %T, v is %#v\n", v, v)// v type is url.Values, v is url.Values{"mq":[]string{"rabbitmq"}, "queue":[]string{"people"}}// 等價(jià)于下面的方法urlString := "https://www.baidu.com/search?mq=rabbitmq&queue=people#12345"u, _ := url.Parse(urlString)queryV := u.Query()fmt.Printf("queryV type is %T, queryV is %#v\n", queryV, queryV)// queryV type is url.Values, queryV is url.Values{"mq":[]string{"rabbitmq"}, "queue":[]string{"people"}}
}
2.2.2 func (Values) Get
func (v Values) Get(key string) string
Get 會(huì)獲取 key 對(duì)應(yīng)的值集的第一個(gè)值。如果沒有對(duì)應(yīng) key 的值集會(huì)返回空字符串。獲取值集請(qǐng)直接用 map 。
2.2.3 func (Values) Set
func (v Values) Set(key, value string)
Set 方法將 key 對(duì)應(yīng)的值集設(shè)為只有 value ,它會(huì)替換掉已有的值集。
2.2.4 func (Values) Add
func (v Values) Add(key, value string)
Add 將 value 添加到 key 關(guān)聯(lián)的值集里原有的值的后面。
2.2.5 func (Values) Del
func (v Values) Del(key string)
Del 刪除 key 關(guān)聯(lián)的值集。
2.2.6 func (Values) Encode
func (v Values) Encode() string
Encode 方法將 v 編碼為 ur 編碼格式(“bar=baz&foo=quux”),編碼時(shí)會(huì)以鍵進(jìn)行排序。
2.2.7 代碼示例
func main() {rawUrl := "mq=rabbitmq&queue=people"v, err := url.ParseQuery(rawUrl)if err != nil {fmt.Println("ParseQuery error ", err)}fmt.Printf("v type is %T, v is %#v\n", v, v)// v type is url.Values, v is url.Values{"mq":[]string{"rabbitmq"}, "queue":[]string{"people"}}fmt.Println(v.Get("mq")) // rabbitmqv.Set("mq", "redis")fmt.Println(v.Get("mq")) // redisv.Add("name", "wohu")fmt.Printf("v is %#v\n", v)// v is url.Values{"mq":[]string{"redis"}, "name":[]string{"wohu"}, "queue":[]string{"people"}}fmt.Printf("v.Encode is %#v\n", v.Encode()) // v.Encode is "mq=redis&name=wohu&queue=people"v.Del("name")fmt.Printf("v is %#v\n", v)// v is url.Values{"mq":[]string{"redis"}, "queue":[]string{"people"}}
}
package mainimport ("fmt""net/url")func main() {v := url.Values{}//公共參數(shù)v.Add("Name", "wohu")v.Add("Age", "18")fmt.Println( v )}
2.3 查詢轉(zhuǎn)義
2.3.1 func QueryEscape
func QueryEscape(s string) string
QueryEscape 函數(shù)對(duì) s 進(jìn)行轉(zhuǎn)碼使之可以安全的用在 URL 查詢里。
2.3.2 func QueryUnescape
func QueryUnescape(s string) (string, error)
QueryUnescape 函數(shù)用于將 QueryEscape 轉(zhuǎn)碼的字符串還原。它會(huì)把 %AB 改為字節(jié) 0xAB ,將 + 改為空格 。如果有某個(gè) % 后面未跟兩個(gè)十六進(jìn)制數(shù)字,本函數(shù)會(huì)返回錯(cuò)誤。
2.3.3 代碼示例
func main() {rawUrl := "mq=rabbitmq&queue=people"stdUrl := url.QueryEscape(rawUrl)fmt.Printf("stdUrl is %v\n", stdUrl) // stdUrl is mq%3Drabbitmq%26queue%3Dpeoplerawurl, _ := url.QueryUnescape(stdUrl)fmt.Printf("rawurl is %v\n", rawurl) // rawurl is mq=rabbitmq&queue=people
}
參考:
https://www.cnblogs.com/wanghui-garcia/p/10424463.html
https://studygolang.com/static/pkgdoc/pkg/net_url.htm
總結(jié)
以上是生活随笔為你收集整理的Go 学习笔记(50)— Go 标准库之 net/url(查询转义、查询参数增/删/改/查、解析URL)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1980年猴票是谁画的啊?
- 下一篇: Go 学习笔记(51)— Go 标准库之