1. URL 概述
import "net/url"
url
包解析 URL
並實現了查詢的轉碼。URL
提供了一種定位因特網上任意資源的手段,但這些資源是可以通過各種不同的方案(比如 HTTP
、 FTP
、 SMTP
)來訪問,因此 URL
語法會隨着方案的不同而不同。
完整的 URL
格式爲:
<schema>://<user>:<password>@<host>:<port>/<path>:<params>?<query>#<frag>
各部分字段說明:
scheme
: 方案是如何訪問指定資源的主要標識符,他會告訴負責解析URL
應用程序應該使用什麼協議;user
:用戶名;password
:密碼;host
: 主機組件標識了因特網上能夠訪問資源的宿主機器,可以有主機名或者是IP
地址來表示;port
: 端口標識了服務器正在監聽的網絡端口。默認端口號是 80;path
:URL
的路徑組件說明了資源位於服務器的什麼地方;params
:URL
中通過協議參數來訪問資源,比名值對列表,分號分割來進行訪問;query
: 字符串是通過提問問題或進行查詢來縮小請求資源類的範圍;frag
: 爲了引用部分資源或資源的一個片段,比如URL
指定HTML
文檔中一個圖片或一個小節;
HTTP
通常只處理整個對象,而不是對象的片段,客戶端不能將片段傳送給服務器。瀏覽器從服務器獲取整個資源之後,會根據片段來顯示你感興趣的片段部分。
2. 主要類型和函數
2.1 type URL
Go
中 URL
結構體如下:
type URL struct {
Scheme string //具體指訪問服務器上的資源使用的哪種協議
Opaque string // 編碼後的不透明數據
User *Userinfo // 用戶名和密碼信息,有些協議需要傳入明文用戶名和密碼來獲取資源,比如 FTP
Host string // host或host:port,服務器地址,可以是 IP 地址,也可以是域名信息
Path string //路徑,使用"/"分隔
RawPath string // 已編碼的路徑提示(參見EscapedPath方法)
ForceQuery bool // 添加一個查詢('?'),即使RawQuery爲空
RawQuery string // 編碼後的查詢字符串,沒有'?'
Fragment string // 引用的片段(文檔位置),沒有'#'
}
示例代碼:
func main() {
urlString := "https://admin:[email protected]: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 false
fmt.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 函數解析
rawurl爲一個
URL結構體,
rawurl` 可以是絕對地址,也可以是相對地址。
2.1.2 func ParseRequestURI
func ParseRequestURI(rawurl string) (url *URL, err error)
ParseRequestURI
函數解析 rawurl
爲一個 URL
結構體,本函數會假設 rawurl
是在一個 HTTP
請求裏,因此會假設該參數是一個絕對 URL
或者絕對路徑,並會假設該 URL
沒有 #fragment
後綴。(網頁瀏覽器會在去掉該後綴後纔將網址發送到網頁服務器)
func main() {
urlString := "https://admin:[email protected]: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
函數在 URL
是絕對 URL
時才返回真。
2.1.4 func (*URL) Query
func (u *URL) Query() Values
Query
方法解析 RawQuery
字段並返回其表示的 Values
類型鍵值對。
2.1.5 func (*URL) RequestURI
func (u *URL) RequestURI() string
RequestURI
方法返回編碼好的 path?query
或 opaque?query
字符串,用在 HTTP
請求裏。
2.1.6 func (*URL) String
func (u *URL) String() string
String
將 URL
重構爲一個合法 URL
字符串。
2.1.7 func (*URL) Parse
func (u *URL) Parse(ref string) (*URL, error)
Parse
方法以 u
爲上下文來解析一個 URL
, ref
可以是絕對或相對 URL
。本方法解析失敗會返回 nil
, err
;否則返回結果和 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
本方法根據一個絕對 URI
將一個 URI
補全爲一個絕對 URI
。參數 ref
可以是絕對 URI
或者相對 URI
。 ResolveReference
總是返回一個新的 URL
實例,即使該實例和 u
或者 ref
完全一樣。如果 ref
是絕對 URI
,本方法會忽略參照 URI
並返回 ref
的一個拷貝。
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 true
fmt.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
將建映射到值的列表。它一般用於查詢的參數和表單的屬性。不同於 http.Header
這個字典類型, Values
的鍵是大小寫敏感的。
2.2.1 func ParseQuery
func ParseQuery(query string) (m Values, err error)
ParseQuery
函數解析一個 URL
編碼的查詢字符串,並返回可以表示該查詢的 Values
類型的字典。本函數總是返回一個包含了所有合法查詢參數的非 nil
字典, err
用來描述解碼時遇到的(如果有)第一個錯誤。
代碼示例:
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"}}
// 等價於下面的方法
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
會獲取 key
對應的值集的第一個值。如果沒有對應 key
的值集會返回空字符串。獲取值集請直接用 map
。
2.2.3 func (Values) Set
func (v Values) Set(key, value string)
Set
方法將 key
對應的值集設爲只有 value
,它會替換掉已有的值集。
2.2.4 func (Values) Add
func (v Values) Add(key, value string)
Add
將 value
添加到 key
關聯的值集裏原有的值的後面。
2.2.5 func (Values) Del
func (v Values) Del(key string)
Del
刪除 key
關聯的值集。
2.2.6 func (Values) Encode
func (v Values) Encode() string
Encode
方法將 v
編碼爲 ur
編碼格式(“bar=baz&foo=quux”),編碼時會以鍵進行排序。
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")) // rabbitmq
v.Set("mq", "redis")
fmt.Println(v.Get("mq")) // redis
v.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"}}
}
2.3 查詢轉義
2.3.1 func QueryEscape
func QueryEscape(s string) string
QueryEscape
函數對 s
進行轉碼使之可以安全的用在 URL
查詢裏。
2.3.2 func QueryUnescape
func QueryUnescape(s string) (string, error)
QueryUnescape
函數用於將 QueryEscape
轉碼的字符串還原。它會把 %AB
改爲字節 0xAB
,將 +
改爲空格 。如果有某個
%
後面未跟兩個十六進制數字,本函數會返回錯誤。
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%3Dpeople
rawurl, _ := 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