脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Go 标准库 net/url 学习笔记

Go 标准库 net/url 学习笔记

2021-08-31 23:32马哥Linux运维 Golang

本文是一篇学习笔记,记录了作者学习 go 语言标准库 net/url 库的过程。

Go 标准库 net/url 学习笔记

本文是一篇学习笔记,记录了作者学习 go 语言标准库 net/url 库的过程。

参考:https://studygolang.com/pkgdoc

导入方式:

  1. import "net/url" 

url 包解析 URL 并实现了查询的逸码,参见 RFC 3986。

func PathEscape

  1. func PathEscape(s string) string 

PathEscape 会将字符串转义出来,以便将其安全地放置在 URL 路径段中。

func PathUnescape 

  1. func PathUnescape(s string) (string, error 

PathUnescape 执行 PathEscape 的逆转换,将 %AB 转换为字节 0xAB 。如果任何 % 之后没有两个十六进制数字,它将返回一个错误。

PathUnescape 与 QueryUnescape 相同,只是它不会将'+'改为''(空格)。

func QueryEscape 

  1. func QueryEscape(s string) string 

QueryEscape 函数对 s 进行转码使之可以安全的用在 URL 查询里。

func QueryUnescape 

  1. func QueryUnescape(s string) (string, error) 

QueryUnescape 函数用于将 QueryEscape 转码的字符串还原。它会把%AB 改为字节 0xAB,将'+'改为' '。如果有某个%后面未跟两个十六进制数字,本函数会返回错误。

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "encoding/base64"  
  5.     "net/url"  
  6.     "crypto/rand"  
  7.     "io"  
  8.     "log"  
  9.  
  10. //sessionId 函数用来生成一个 session ID,即 session 的唯一标识符  
  11. func sessionId() string {  
  12.     b :make([]byte, 32)  
  13.     //ReadFull 从 rand.Reader 精确地读取 len(b) 字节数据填充进 b  
  14.     //rand.Reader 是一个全局、共享的密码用强随机数生成器  
  15.     if _, err :io.ReadFull(rand.Reader, b); err != nil {   
  16.         return ""  
  17.     }  
  18.     fmt.Println(b) //[238 246 235 166 48 196 157 143 123 140 241 200 213 113 247 168 219 132 208 163 223 24 72 162 114 30 175 205 176 117 139 118] 
  19.      return base64.URLEncoding.EncodeToString(b)//将生成的随机数 b 编码后返回字符串,该值则作为 session ID 
  20.   
  21. func main() {   
  22.     sessionId :sessionId()   
  23.     fmt.Println(sessionId) //7vbrpjDEnY97jPHI1XH3qNuE0KPfGEiich6vzbB1i3Y 
  24.     encodedSessionId :url.QueryEscape(sessionId) //对 sessionId 进行转码使之可以安全的用在 URL 查询里  
  25.     fmt.Println(encodedSessionId) //7vbrpjDEnY97jPHI1XH3qNuE0KPfGEiich6vzbB1i3Y%3D  
  26.     decodedSessionId, err :url.QueryUnescape(encodedSessionId) //将 QueryEscape 转码的字符串还原  
  27.     if err != nil {  
  28.         log.Fatal(err)  
  29.     }  
  30.     fmt.Println(decodedSessionId) //7vbrpjDEnY97jPHI1XH3qNuE0KPfGEiich6vzbB1i3Y 

type URL 

  1. type URL struct {  
  2.     Scheme   string    //具体指访问服务器上的资源使用的哪种协议  
  3.     Opaque   string    // 编码后的不透明数据  
  4.     User     *Userinfo // 用户名和密码信息,有些协议需要传入明文用户名和密码来获取资源,比如 FTP  
  5.     Host     string    // host 或 host:port,服务器地址,可以是 IP 地址,也可以是域名信息  
  6.     Path     string  //路径,使用"/"分隔  
  7.     RawQuery string // 编码后的查询字符串,没有'?'  
  8.     Fragment string // 引用的片段(文档位置),没有'#'  

URL 类型代表一个解析后的 URL(或者说,一个 URL 参照)。URL 基本格式如下:

  1. scheme://[userinfo@]host/path[?query][#fragment] 

scheme 后不是冒号加双斜线的 URL 被解释为如下格式:

  1. scheme:opaque[?query][#fragment] 

注意路径字段是以解码后的格式保存的,如/%47%6f%2f 会变成/Go/。这导致我们无法确定 Path 字段中的斜线是来自原始 URL 还是解码前的%2f。除非一个客户端必须使用其他程序/函数来解析原始 URL 或者重构原始 URL,这个区别并不重要。此时,HTTP 服务端可以查询 req.RequestURI,而 HTTP 客户端可以使用 URL{Host: "example.com", Opaque: "//example.com/Go%2f"}代替{Host: "example.com", Path: "/Go/"}。

func Parse 

  1. func Parse(rawurl string) (url *URL, err error) 

Parse 函数解析 rawurl 为一个 URL 结构体,rawurl 可以是绝对地址,也可以是相对地址。

func ParseRequestURI 

  1. func ParseRequestURI(rawurl string) (url *URL, err error) 

ParseRequestURI 函数解析 rawurl 为一个 URL 结构体,本函数会假设 rawurl 是在一个 HTTP 请求里,因此会假设该参数是一个绝对 URL 或者绝对路径,并会假设该 URL 没有#fragment 后缀。(网页浏览器会在去掉该后缀后才将网址发送到网页服务器)

func (*URL) IsAbs

  1. func (u *URL) IsAbs() bool 

函数在 URL 是绝对 URL 时才返回真。

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.  
  6. func main() {   
  7.     u :url.URL{Host: "example.com", Path: "foo"}  
  8.     fmt.Println(u.IsAbs()) //false  
  9.     u.Scheme = "http"  
  10.     fmt.Println(u.IsAbs()) //true  

func (*URL) Query 

  1. func (u *URL) Query() Values 

Query 方法解析 RawQuery 字段并返回其表示的 Values 类型键值对。

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.  
  6. func main() {   
  7.     u := &url.URL{  
  8.         Scheme:   "https",  
  9.         User:     url.UserPassword("me", "pass"),  
  10.         Host:     "example.com",  
  11.         Path:     "foo/bar",  
  12.         RawQuery: "x=1&y=2",  
  13.         Fragment: "anchor",  
  14.     }  
  15.     fmt.Println(u.Query()) //map[x:[1] y:[2]]  

func (*URL) RequestURI 

  1. func (u *URL) RequestURI() string 

RequestURI 方法返回编码好的 path?query 或 opaque?query 字符串,用在 HTTP 请求里。

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.     "log"  
  6.  
  7. func main() {   
  8.     u, err :url.Parse("https://example.org/path?foo=bar")  
  9.     if err != nil {  
  10.         log.Fatal(err)  
  11.     }  
  12.     fmt.Println(u.RequestURI()) ///path?foo=bar  

func (*URL) String 

  1. func (u *URL) String() string 

String 将 URL 重构为一个合法 URL 字符串。

字符串将 URL 重组为一个有效的 URL 字符串。结果的一般形式是以下之一:

  1. scheme:opaque?query#fragment  
  2. scheme://userinfo@host/path?query#fragment 

如果 u.Opaque 不为空,则 String 使用第一种形式;否则它使用第二种形式。要获取路径,String 使用 u.EscapedPath() 。

在第二种形式中,适用下列规则:

  1. - if u.Scheme is empty, scheme: is omitted.  
  2. - if u.User is nil, userinfo@ is omitted.  
  3. - if u.Host is empty, host/ is omitted.  
  4. - if u.Scheme and u.Host are empty and u.User is nil,  
  5.    the entire scheme://userinfo@host/ is omitted.  
  6. - if u.Host is non-empty and u.Path begins with a /,  
  7.    the form host/path does not add its own /.  
  8. - if u.RawQuery is empty, ?query is omitted.  
  9. - if u.Fragment is empty, #fragment is omitted. 

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.  
  6. func main() {   
  7.     u := &url.URL{  
  8.         Scheme:   "https",  
  9.         User:     url.UserPassword("me", "pass"),  
  10.         Host:     "example.com",  
  11.         Path:     "foo/bar",  
  12.         RawQuery: "x=1&y=2",  
  13.         Fragment: "anchor",  
  14.     }  
  15.     //这是第一种形式  
  16.     fmt.Println(u.String()) //https://me:pass@example.com/foo/bar?x=1&y=2#anchor  
  17.     u.Opaque = "opaque"  
  18.     //这是第二种形式  
  19.     fmt.Println(u.String()) //https:opaque?x=1&y=2#anchor  

func (*URL) EscapedPath 

  1. func (u *URL) EscapedPath() string 

EscapedPath 返回 u.Path 的转义形式。一般来说,任何路径都有多种可能的转义形式。EscapedPath 在 u.Path 有效转义时返回 u.RawPath 。否则,EscapedPath 将忽略 u.RawPath 并自行计算转义表单。String 和 RequestURI 方法使用 EscapedPath 来构造它们的结果。通常,代码应该调用 EscapedPath ,而不是直接读取 u.RawPath 。

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.     "log"  
  6.  
  7. func main() {   
  8.     u, err :url.Parse("http://example.com/path with spaces")  
  9.     if err != nil {  
  10.         log.Fatal(err)  
  11.     }  
  12.     fmt.Println(u.EscapedPath()) ///path%20with%20spaces  

func (*URL) Hostname 

  1. func (u *URL) Hostname() string 

主机名返回 u.Host ,没有任何端口号。

如果主机是具有端口号的 IPv6 文本,则主机名将返回不带方括号的 IPv6 文字。IPv6 文字可能包含区域标识符。

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.     "log"  
  6.  
  7. func main() {   
  8.     u, err :url.Parse("https://example.org:8000/path")//IPV4  
  9.     if err != nil {  
  10.         log.Fatal(err)  
  11.     }  
  12.     fmt.Println(u.Hostname()) //example.org  
  13.     u, err = url.Parse("https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:17000") //IPV6  
  14.     if err != nil {  
  15.         log.Fatal(err)  
  16.     }  
  17.     fmt.Println(u.Hostname())//2001:0db8:85a3:0000:0000:8a2e:0370:7334  

func (*URL) Port 

  1. func (u *URL) Port() string 

Port 返回 u.Host 的端口部分,不带前导冒号。如果 u.Host 不包含端口,则 Port 返回空字符串。

func (*URL) Parse 

  1. func (u *URL) Parse(ref string) (*URL, error) 

Parse 方法以 u 为上下文来解析一个 URL,ref 可以是绝对或相对 URL。

本方法解析失败会返回 nil, err;否则返回结果和 ResolveReference 一致。

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.     "log"  
  6.  
  7. func main() {   
  8.     base, err :url.Parse("http://example.com/directory/")  
  9.     if err != nil {  
  10.         log.Fatal(err)  
  11.     }  
  12.     fmt.Println(base)  
  13.     result, err :base.Parse("./search?q=dotnet")  
  14.     if err != nil {  
  15.         log.Fatal(err) 
  16.     }  
  17.     fmt.Println(result)  

返回:

  1. bogon:~ user$ go run testGo.go   
  2. http://example.com/directory/  
  3. http://example.com/directory/search?q=dotnet 

func (*URL) ResolveReference 

  1. func (u *URL) ResolveReference(ref *URL) *URL 

本方法根据一个绝对 URI 将一个 URI 补全为一个绝对 URI,参见 RFC 3986 节 5.2。参数 ref 可以是绝对 URI 或者相对 URI。ResolveReference 总是返回一个新的 URL 实例,即使该实例和 u 或者 ref 完全一样。如果 ref 是绝对 URI,本方法会忽略参照 URI 并返回 ref 的一个拷贝。

举例:

当 ref 是相对路径,则其将会相对于 u 来得到其的绝对路径:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.     "log"  
  6.  
  7. func main() {   
  8.   //该相对路径的意思是  
  9.     u, err :url.Parse("../../..//search?q=dotnet")//相对路径的不同会影响返回的结果  
  10.     if err != nil {  
  11.         log.Fatal(err) 
  12.      }  
  13.     fmt.Println(u) 
  14.      base, err :url.Parse("http://example.com/directory/")  
  15.     if err != nil {  
  16.         log.Fatal(err)  
  17.     }  
  18.     fmt.Println(base)  
  19.     fmt.Println(base.ResolveReference(u))  

返回:

  1. bogon:~ user$ go run testGo.go   
  2. ../../..//search?q=dotnet  
  3. http://example.com/directory/  
  4. http://example.com/search?q=dotnet 

如果相对路径为。./..//search?q=dotnet,返回结果是相同的,即 http://example.com/search?q=dotnet

但是如果相对路径为。.//search?q=dotnet,将返回 http://example.com//search?q=dotnet,这并不是我们想要的结果。如果想要相对于 directory 目录,则相对路径写成。/search?q=dotnet

func (u *URL) MarshalBinary() (text []byte, err error) 

  1. func (u *URL) MarshalBinary() (text []byte, err error) 

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.     "log"  
  6.     "reflect"  
  7.  
  8. func main() {   
  9.     u, _ :url.Parse("https://example.org")  
  10.     b, err :u.MarshalBinary() //将其转成二进制  
  11.     if err != nil {  
  12.         log.Fatal(err)  
  13.     }  
  14.     fmt.Println(reflect.TypeOf(b)) //[]uint8  
  15.     fmt.Println(b) //[104 116 116 112 115 58 47 47 101 120 97 109 112 108 101 46 111 114 103]  
  16.     fmt.Printf("%s\n", b) //https://example.org  

func (*URL) UnmarshalBinary 

  1. func (u *URL) UnmarshalBinary(text []byte) error 

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.     "log"  
  6.     "reflect"  
  7.  
  8. func main() {   
  9.     u := &url.URL{}  
  10.     //将其从二进制转成 url.URL 类型  
  11.     err :u.UnmarshalBinary([]byte("https://example.org:8000/foo"))  
  12.     if err != nil {  
  13.         log.Fatal(err)  
  14.     }  
  15.     fmt.Println(reflect.TypeOf(u)) //*url.URL  
  16.     fmt.Println(u) //https://example.org:8000/foo  
  17.     fmt.Println(u.Hostname()) //example.org  
  18.     fmt.Println(u.Port()) //8000 

type Userinfo 

  1. type Userinfo struct {  
  2.     // 内含隐藏或非导出字段  

Userinfo 类型是一个 URL 的用户名和密码细节的一个不可修改的封装。一个真实存在的 Userinfo 值必须保证有用户名(但根据 RFC 2396 可以是空字符串)以及一个可选的密码。

func User

  1. func User(username string) *Userinfo 

User 函数返回一个用户名设置为 username 的不设置密码的* Userinfo。

func UserPassword 

  1. func UserPassword(username, password string) *Userinfo 

UserPassword 函数返回一个用户名设置为 username、密码设置为 password 的* Userinfo。

这个函数应该只用于老式的站点,因为风险很大,不建议使用,参见 RFC 2396。

func (*Userinfo) Username 

  1. func (u *Userinfo) Username() string 

Username 方法返回用户名。

func (*Userinfo) Password 

  1. func (u *Userinfo) Password() (string, bool) 

如果设置了密码返回密码和真,否则会返回假。

func (*Userinfo) String 

  1. func (u *Userinfo) String() string 

String 方法返回编码后的用户信息,格式为"username[:password]"。

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.     "log"  
  6.  
  7. func main() {   
  8.     u := &url.URL{  
  9.         Scheme:   "https",  
  10.         User:     url.UserPassword("me", "pass"),  
  11.         Host:     "example.com",  
  12.         Path:     "foo/bar",  
  13.         RawQuery: "x=1&y=2",  
  14.         Fragment: "anchor",  
  15.     }  
  16.     fmt.Println(u.User.Username()) //me  
  17.     password, b :u.User.Password()  
  18.     if b == false{  
  19.         log.Fatal("can not get password")  
  20.     }  
  21.     fmt.Println(password) //pass  
  22.     fmt.Println(u.User.String()) //me:pass  

type Values 

  1. type Values map[string][]string 

Values 将建映射到值的列表。它一般用于查询的参数和表单的属性。不同于 http.Header 这个字典类型,Values 的键是大小写敏感的。

func ParseQuery 

  1. func ParseQuery(query string) (m Values, err error) 

ParseQuery 函数解析一个 URL 编码的查询字符串,并返回可以表示该查询的 Values 类型的字典。本函数总是返回一个包含了所有合法查询参数的非 nil 字典,err 用来描述解码时遇到的(如果有)第一个错误。

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5.     "log"  
  6.  
  7. func main() {   
  8.     v, err :url.ParseQuery("friend=Jess&friend=Sarah&fruit=apple&name=Ava")  
  9.     if err != nil {  
  10.         log.Fatal(err)  
  11.     }  
  12.     fmt.Println(v) //map[friend:[Jess Sarah] fruit:[apple] name:[Ava]]  

func (Values) Get 

  1. func (v Values) Get(key string) string 

Get 会获取 key 对应的值集的第一个值。如果没有对应 key 的值集会返回空字符串。获取值集请直接用 map。

func (Values) Set 

  1. func (v Values) Set(key, value string) 

Set 方法将 key 对应的值集设为只有 value,它会替换掉已有的值集。

func (Values) Add 

  1. func (v Values) Add(key, value string) 

Add 将 value 添加到 key 关联的值集里原有的值的后面。

func (Values) Del 

  1. func (v Values) Del(key string) 

Del 删除 key 关联的值集。

func (Values) Encode 

  1. func (v Values) Encode() string 

Encode 方法将 v 编码为 url 编码格式 ("bar=baz&foo=quux"),编码时会以键进行排序。

举例:

  1. package main   
  2. import(  
  3.     "fmt"  
  4.     "net/url"  
  5. func main() {   
  6.     v :url.Values{}  
  7.     v.Set("name", "Ava")  
  8.     v.Add("friend", "Jess")  
  9.     v.Add("friend", "Sarah")  
  10.     v.Add("fruit", "apple")  
  11.     fmt.Println(v.Get("name"))  
  12.     fmt.Println(v.Get("friend"))  
  13.     fmt.Println(v["friend"])  
  14.     fmt.Println(v.Encode())  
  15.     v.Del("name")  
  16.     fmt.Println(v.Encode())  

返回:

  1. bogon:~ user$ go run testGo.go   
  2. Ava  
  3. Jess  
  4. [Jess Sarah]  
  5. friend=Jess&friend=Sarah&fruit=apple&name=Ava  
  6. friend=Jess&friend=Sarah&fruit=apple 

原文地址:https://mp.weixin.qq.com/s/g5GNaXxWxzznB5iG1-aBwg

延伸 · 阅读

精彩推荐
  • Golanggolang的httpserver优雅重启方法详解

    golang的httpserver优雅重启方法详解

    这篇文章主要给大家介绍了关于golang的httpserver优雅重启的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    helight2992020-05-14
  • Golanggo日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang 通过ssh代理连接mysql的操作

    golang 通过ssh代理连接mysql的操作

    这篇文章主要介绍了golang 通过ssh代理连接mysql的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    a165861639710342021-03-08
  • GolangGolang通脉之数据类型详情

    Golang通脉之数据类型详情

    这篇文章主要介绍了Golang通脉之数据类型,在编程语言中标识符就是定义的具有某种意义的词,比如变量名、常量名、函数名等等,Go语言中标识符允许由...

    4272021-11-24
  • Golanggo语言制作端口扫描器

    go语言制作端口扫描器

    本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下。 ...

    脚本之家3642020-04-25
  • GolangGolang中Bit数组的实现方式

    Golang中Bit数组的实现方式

    这篇文章主要介绍了Golang中Bit数组的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    天易独尊11682021-06-09
  • Golanggolang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    李浩的life12792020-05-27
  • Golanggolang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看...

    Go语言中文网11352020-05-21