继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

『Go 内置库第一季:net/url』

慕的地10843
关注TA
已关注
手记 1081
粉丝 200
获赞 962

webp

TEACHING_GOPHER.png

大家好,我叫谢伟,是一名程序员。

近期会同步内置库的学习,主要参考文献官方文档和源代码

本节的主题:url

其实这是一个比较小的内置函数,主要用在网络请求方面上,可能最多的用途也就是用来处理网络请求的参数。当然如何你经常在项目中编写restfulAPI, 那么你也可能经常用到。

大纲:

  • 原理知识

  • 基本的用法

  • 学习到了什么

1. 原理知识

URL: Uniform Resource Location, 称之为统一资源定位符。

出现的背景是:打个比方,比如你要找家里的东西,首先,你是不是会对东西的归属分析,比如,一把菜刀,你最大的可能是去厨房吧,这样能大概率的找到。网络上的资源也是这样,为了精准的找到服务器上的资源,有了 url。

那关于 url 有哪些知识呢?

  • 代表的含义

  • 组成部分:你要知道 url 的具体形式是什么吧

  • 语法

1.1 代表的含义

就字面上的意思:统一资源定位符,唯一定位网络上的资源。

1.2 组成的部分

首先给个实例:

https://www.google.com
  • 方案 scheme: 主要表示的是使用的是何种协议,比如 HTTP,FTP 等

  • 服务器的地址: 你可以使用 ip 地址,也可以使用域名,所以IP 地址到域名之间存在一个映射关系

  • 资源路径: 这部分就针对的是网络具体的资源的地址

这个好理解吧,和我们日常中的家庭地址、公司地址一样的含义,先定位省份,再定位市区,继而继续定位下去,直到找到你的地址。

网络的上资源,基本上还是借用这套思路:先定位到服务器上的地址,继而定位到具体的资源的地址。URL 就是这个意思。

1.3 语法组成

为了规范这些网络上的资源的地址,需要有一套规范,这套语法到底包含哪些东西?

  • 方案: scheme ,具体指访问服务器上的资源使用的哪种协议

  • 用户: 有些协议可以传入明文用户名和密码获取资源,比如 FTP

  • 密码

  • 主机: 服务器地址,可以是 IP 地址,也可以是域名信息

  • 端口: 一串数字

  • 路径: 资源的路径,使用 “/” 分隔

  • 参数: example=one&hello=world 类似于这样的键值对

  • 查询: 标识符是 “?” 和参数配合使用

  • 片段: 标识符是 ”#“

好,不好理解,举个例子:

https://godoc.org/net/url#example-Values
  • scheme: https

  • 用户: 无

  • 密码: 无

  • 主机: godoc.org

  • 端口: 无

  • 路径: net/url

  • 参数: 无

  • 查询: 无

  • 片段: example-Values

有些是可选项,所以到最后,常用的是这几个概念:

  • scheme(方案、协议)

  • host(服务器地址)

  • port(服务器端口)

  • path(路径)

  • params(参数)

  • fragment(片段)

另外在请求的过程中还存在一个问题:编码,用来在URL 中表示各种不安全的字符

常见的编码:

字符示例
~%7
空格%20
%%25

2. 基本用法

和根据上文的解释,我们明白 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 mainimport (    "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     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 '#'}

看上去,和我们预想的差别不大,但作者想的比我们深,比如把编码也考虑进去了,所有会有RawQuery,RawPath 等字段。

继续查看:

func PathEscape(s string) stringfunc PathUnescape(s string) (string, error)func QueryEscape(s string) stringfunc QueryUnescape(s string) (string, error)type Errorfunc (e *Error) Error() stringfunc (e *Error) Temporary() boolfunc (e *Error) Timeout() booltype EscapeErrorfunc (e EscapeError) Error() stringtype InvalidHostErrorfunc (e InvalidHostError) Error() stringtype URLfunc Parse(rawurl string) (*URL, error)func ParseRequestURI(rawurl string) (*URL, error)func (u *URL) EscapedPath() stringfunc (u *URL) Hostname() stringfunc (u *URL) IsAbs() boolfunc (u *URL) MarshalBinary() (text []byte, err error)func (u *URL) Parse(ref string) (*URL, error)func (u *URL) Port() stringfunc (u *URL) Query() Valuesfunc (u *URL) RequestURI() stringfunc (u *URL) ResolveReference(ref *URL) *URLfunc (u *URL) String() stringfunc (u *URL) UnmarshalBinary(text []byte) errortype Userinfofunc User(username string) *Userinfofunc UserPassword(username, password string) *Userinfofunc (u *Userinfo) Password() (string, bool)func (u *Userinfo) String() stringfunc (u *Userinfo) Username() stringtype Valuesfunc 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)

可以看出,重要的用法有:

  • 将字符串转化成 URL 对象,URL 对象获取相应的组成成分,存在相应的方法

  • URL 中的参数 Values 很重要,特别是我们编写 restfulAPI 的过程,也会思考这个问题,请求参数。 她的底层是 map[string][]string , 所以可以Add, Del, Get,Set等方法,这个东西需要记住,下次我们分析 net/http 库的一个重要部分就是:对请求参数的处理

最后,再看下,这个库对错误的处理:

type EscapeError stringfunc (e EscapeError) Error() string {    return "invalid URL escape " + strconv.Quote(string(e))
}

type InvalidHostError stringfunc (e InvalidHostError) Error() string {    return "invalid character " + strconv.Quote(string(e)) + " in host name"}
  • 定义一个结构体

  • 实现 Error 方法,继而实现 error 接口

3. 学到了什么

  1. 站在设计者的角度思考,我应该怎么设计?

  2. 如何设计的思路来源于原理,而不是胡乱思考。

  3. 返过来再去看书本中的原理



作者:谢小路
链接:https://www.jianshu.com/p/54b2639fb326


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP