你们好,我叫谢伟,是一名程序员。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"
}
复制代码
<完>