你們好,我叫謝偉,是一名程序員。html
近期會同步內置庫的學習,主要參考文獻官方文檔和源代碼程序員
本節的主題:urljson
其實這是一個比較小的內置函數,主要用在網絡請求方面上,可能最多的用途也就是用來處理網絡請求的參數。固然如何你常常在項目中編寫restfulAPI, 那麼你也可能常常用到。後端
大綱:api
URL: Uniform Resource Location, 稱之爲統一資源定位符。安全
出現的背景是:打個比方,好比你要找家裏的東西,首先,你是否是會對東西的歸屬分析,好比,一把菜刀,你最大的多是去廚房吧,這樣能大機率的找到。網絡上的資源也是這樣,爲了精準的找到服務器上的資源,有了 url。bash
那關於 url 有哪些知識呢?服務器
就字面上的意思:統一資源定位符,惟必定位網絡上的資源。restful
首先給個實例:網絡
https://www.google.com
複製代碼
這個好理解吧,和咱們平常中的家庭地址、公司地址同樣的含義,先定位省份,再定位市區,繼而繼續定位下去,直到找到你的地址。
網絡的上資源,基本上仍是借用這套思路:先定位到服務器上的地址,繼而定位到具體的資源的地址。URL 就是這個意思。
爲了規範這些網絡上的資源的地址,須要有一套規範,這套語法到底包含哪些東西?
好,很差理解,舉個例子:
https://godoc.org/net/url#example-Values
複製代碼
有些是可選項,因此到最後,經常使用的是這幾個概念:
另外在請求的過程當中還存在一個問題:編碼,用來在URL 中表示各類不安全的字符
常見的編碼:
字符 | 示例 |
---|---|
~ | %7 |
空格 | %20 |
% | %25 |
和根據上文的解釋,咱們明白 URL 的含義,但最終的它實際上是一串字符串,只不過在網絡資源請求層面,這串字符串賦予了更多的含義。
先撇開,官方的內置庫的用法,咱們首先想要本身實現,如何操做?
根據 url 的組成, 咱們可能會設計以下面這個樣子
type Url struct {
Scheme string
User string
Password string
Host string
Port string
Path string
Params map[string][]string
Fragment string
}
複製代碼
好,假如設計成這樣,咱們將一串字符串轉化成 咱們定義的類型 Url, 如何獲得各個部分呢?
https://godoc.org/net/url#example-Values
複製代碼
對照着各個含義,那麼咱們的思路應該是對這串字符的處理,好比按:,//,/,#
等劃分獲得咱們須要的內容。
以上是咱們本身的思考,若是感興趣,能夠本身單獨實現下,想一想:本身會提供哪些公開的方法?又會設計些什麼輔助的功能?
下面查看官方的實現:
示例:
package main
import (
"fmt"
"net/url"
)
var urlCollection struct {
urlOne string
urlTwo string
urlThree string
urlFour string
urlFive string
}
func init() {
urlCollection.urlOne = "https://www.google.com"
urlCollection.urlTwo = "http://localhost:8887/v1/api/cloud_api/fetcher?email=1156143589@qq.com"
// https://developer.readsense.cn/docs/retail/retailv2/regions.html#刪除區域
urlCollection.urlThree = "https://developer.readsense.cn/docs/retail/retailv2/regions.html#%E5%88%A0%E9%99%A4%E5%8C%BA%E5%9F%9F"
urlCollection.urlFour = "https://joe:joepassword@www.email.com/share_info.txt"
urlCollection.urlFive = "https://godoc.org/net/url#example-Values"
}
func main() {
OpUrl(urlCollection.urlOne)
OpUrl(urlCollection.urlTwo)
OpUrl(urlCollection.urlThree)
OpUrl(urlCollection.urlFour)
OpUrl(urlCollection.urlFive)
}
func OpUrl(urlString string) {
URL, _ := url.Parse(urlString)
fmt.Println("user", URL.User)
fmt.Println("scheme", URL.Scheme)
fmt.Println("host", URL.Host)
fmt.Println("port", URL.Port())
fmt.Println("rawQuery", URL.RawQuery)
fmt.Println("rawPath", URL.RawPath)
fmt.Println("path", URL.Path)
fmt.Println("forceQuery", URL.ForceQuery)
fmt.Println("fragment", URL.Fragment)
}
複製代碼
能夠看出:url.Parse
能夠將字符串轉化成 URL 對象,該對象包含:User,Scheme,Host,Path,RawPath,ForceQuery,Fragment
字段和一些方法。
查看源代碼,看URL 類型對象是如何定義?
type URL struct {
Scheme string
Opaque string // encoded opaque data
User *Userinfo // username and password information
Host string // host or host:port
Path 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 empty
RawQuery string // encoded query values, without '?'
Fragment string // fragment for references, without '#'
}
複製代碼
看上去,和咱們預想的差異不大,但做者想的比咱們深,好比把編碼也考慮進去了,全部會有RawQuery,RawPath 等字段。
繼續查看:
func PathEscape(s string) string func PathUnescape(s string) (string, error) func QueryEscape(s string) string func QueryUnescape(s string) (string, error) type Error func (e *Error) Error() string func (e *Error) Temporary() bool func (e *Error) Timeout() bool type EscapeError func (e EscapeError) Error() string type InvalidHostError func (e InvalidHostError) Error() string type URL func Parse(rawurl string) (*URL, error) func ParseRequestURI(rawurl string) (*URL, error) func (u *URL) EscapedPath() string func (u *URL) Hostname() string func (u *URL) IsAbs() bool func (u *URL) MarshalBinary() (text []byte, err error) func (u *URL) Parse(ref string) (*URL, error) func (u *URL) Port() string func (u *URL) Query() Values func (u *URL) RequestURI() string func (u *URL) ResolveReference(ref *URL) *URL func (u *URL) String() string func (u *URL) UnmarshalBinary(text []byte) error type Userinfo func User(username string) *Userinfo func UserPassword(username, password string) *Userinfo func (u *Userinfo) Password() (string, bool) func (u *Userinfo) String() string func (u *Userinfo) Username() string type Values func ParseQuery(query string) (Values, error) func (v Values) Add(key, value string) func (v Values) Del(key string) func (v Values) Encode() string func (v Values) Get(key string) string func (v Values) Set(key, value string) 複製代碼
能夠看出,重要的用法有:
map[string][]string
, 因此能夠Add, Del, Get,Set
等方法,這個東西須要記住,下次咱們分析 net/http
庫的一個重要部分就是:對請求參數的處理最後,再看下,這個庫對錯誤的處理:
type EscapeError string
func (e EscapeError) Error() string {
return "invalid URL escape " + strconv.Quote(string(e))
}
type InvalidHostError string
func (e InvalidHostError) Error() string {
return "invalid character " + strconv.Quote(string(e)) + " in host name"
}
複製代碼
<完>