go标准库的学习-net/url
参考:https://studygolang.com/pkgdoc
导入方式:
import "net/url"
url包解析URL并实现了查询的逸码,参见RFC 3986。
func PathEscape
func PathEscape(s string) string
PathEscape 会将字符串转义出来,以便将其安全地放置在 URL 路径段中。
func PathUnescape
func PathUnescape(s string) (string, error
PathUnescape 执行 PathEscape 的逆转换,将 %AB 转换为字节 0xAB 。如果任何 % 之后没有两个十六进制数字,它将返回一个错误。
PathUnescape 与 QueryUnescape 相同,只是它不会将'+'改为''(空格)。
func QueryEscape
func QueryEscape(s string) string
QueryEscape函数对s进行转码使之可以安全的用在URL查询里。
func QueryUnescape
func QueryUnescape(s string) (string, error)
QueryUnescape函数用于将QueryEscape转码的字符串还原。它会把%AB改为字节0xAB,将'+'改为' '。如果有某个%后面未跟两个十六进制数字,本函数会返回错误。
举例:
package main
import(
"fmt"
"encoding/base64"
"net/url"
"crypto/rand"
"io"
"log"
) //sessionId函数用来生成一个session ID,即session的唯一标识符
func sessionId() string {
b := make([]byte, )
//ReadFull从rand.Reader精确地读取len(b)字节数据填充进b
//rand.Reader是一个全局、共享的密码用强随机数生成器
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return ""
}
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]
return base64.URLEncoding.EncodeToString(b)//将生成的随机数b编码后返回字符串,该值则作为session ID
}
func main() {
sessionId := sessionId()
fmt.Println(sessionId) //7vbrpjDEnY97jPHI1XH3qNuE0KPfGEiich6vzbB1i3Y=
encodedSessionId := url.QueryEscape(sessionId) //对sessionId进行转码使之可以安全的用在URL查询里
fmt.Println(encodedSessionId) //7vbrpjDEnY97jPHI1XH3qNuE0KPfGEiich6vzbB1i3Y%3D
decodedSessionId, err := url.QueryUnescape(encodedSessionId) //将QueryEscape转码的字符串还原
if err != nil {
log.Fatal(err)
}
fmt.Println(decodedSessionId) //7vbrpjDEnY97jPHI1XH3qNuE0KPfGEiich6vzbB1i3Y=
}
type URL
type URL struct {
Scheme string //具体指访问服务器上的资源使用的哪种协议
Opaque string // 编码后的不透明数据
User *Userinfo // 用户名和密码信息,有些协议需要传入明文用户名和密码来获取资源,比如 FTP
Host string // host或host:port,服务器地址,可以是 IP 地址,也可以是域名信息
Path string //路径,使用"/"分隔
RawQuery string // 编码后的查询字符串,没有'?'
Fragment string // 引用的片段(文档位置),没有'#'
}
URL类型代表一个解析后的URL(或者说,一个URL参照)。URL基本格式如下:
scheme://[userinfo@]host/path[?query][#fragment]
scheme后不是冒号加双斜线的URL被解释为如下格式:
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
func Parse(rawurl string) (url *URL, err error)
Parse函数解析rawurl为一个URL结构体,rawurl可以是绝对地址,也可以是相对地址。
func ParseRequestURI
func ParseRequestURI(rawurl string) (url *URL, err error)
ParseRequestURI函数解析rawurl为一个URL结构体,本函数会假设rawurl是在一个HTTP请求里,因此会假设该参数是一个绝对URL或者绝对路径,并会假设该URL没有#fragment后缀。(网页浏览器会在去掉该后缀后才将网址发送到网页服务器)
func (*URL) IsAbs
func (u *URL) IsAbs() bool
函数在URL是绝对URL时才返回真。
举例:
package main
import(
"fmt"
"net/url"
) func main() {
u := url.URL{Host: "example.com", Path: "foo"}
fmt.Println(u.IsAbs()) //false
u.Scheme = "http"
fmt.Println(u.IsAbs()) //true
}
func (*URL) Query
func (u *URL) Query() Values
Query方法解析RawQuery字段并返回其表示的Values类型键值对。
举例:
package main
import(
"fmt"
"net/url"
) func main() {
u := &url.URL{
Scheme: "https",
User: url.UserPassword("me", "pass"),
Host: "example.com",
Path: "foo/bar",
RawQuery: "x=1&y=2",
Fragment: "anchor",
}
fmt.Println(u.Query()) //map[x:[1] y:[2]]
}
func (*URL) RequestURI
func (u *URL) RequestURI() string
RequestURI方法返回编码好的path?query或opaque?query字符串,用在HTTP请求里。
package main
import(
"fmt"
"net/url"
"log"
) func main() {
u, err := url.Parse("https://example.org/path?foo=bar")
if err != nil {
log.Fatal(err)
}
fmt.Println(u.RequestURI()) ///path?foo=bar
}
func (*URL) String
func (u *URL) String() string
String将URL重构为一个合法URL字符串。
字符串将 URL 重组为一个有效的 URL 字符串。结果的一般形式是以下之一:
scheme:opaque?query#fragment
scheme://userinfo@host/path?query#fragment
如果 u.Opaque 不为空,则 String 使用第一种形式; 否则它使用第二种形式。要获取路径,String 使用 u.EscapedPath() 。
在第二种形式中,适用下列规则:
- if u.Scheme is empty, scheme: is omitted.
- if u.User is nil, userinfo@ is omitted.
- if u.Host is empty, host/ is omitted.
- if u.Scheme and u.Host are empty and u.User is nil,
the entire scheme://userinfo@host/ is omitted.
- if u.Host is non-empty and u.Path begins with a /,
the form host/path does not add its own /.
- if u.RawQuery is empty, ?query is omitted.
- if u.Fragment is empty, #fragment is omitted.
举例:
package main
import(
"fmt"
"net/url"
) func main() {
u := &url.URL{
Scheme: "https",
User: url.UserPassword("me", "pass"),
Host: "example.com",
Path: "foo/bar",
RawQuery: "x=1&y=2",
Fragment: "anchor",
}
//这是第一种形式
fmt.Println(u.String()) //https://me:pass@example.com/foo/bar?x=1&y=2#anchor
u.Opaque = "opaque"
//这是第二种形式
fmt.Println(u.String()) //https:opaque?x=1&y=2#anchor
}
func (*URL) EscapedPath
func (u *URL) EscapedPath() string
EscapedPath 返回 u.Path 的转义形式。一般来说,任何路径都有多种可能的转义形式。EscapedPath 在 u.Path 有效转义时返回 u.RawPath 。否则,EscapedPath 将忽略 u.RawPath 并自行计算转义表单。 String 和 RequestURI 方法使用 EscapedPath 来构造它们的结果。通常,代码应该调用 EscapedPath ,而不是直接读取 u.RawPath 。
举例:
package main
import(
"fmt"
"net/url"
"log"
) func main() {
u, err := url.Parse("http://example.com/path with spaces")
if err != nil {
log.Fatal(err)
}
fmt.Println(u.EscapedPath()) ///path%20with%20spaces
}
func (*URL) Hostname
func (u *URL) Hostname() string
主机名返回 u.Host ,没有任何端口号。
如果主机是具有端口号的 IPv6 文本,则主机名将返回不带方括号的 IPv6 文字。IPv6 文字可能包含区域标识符。
举例:
package main
import(
"fmt"
"net/url"
"log"
) func main() {
u, err := url.Parse("https://example.org:8000/path")//IPV4
if err != nil {
log.Fatal(err)
}
fmt.Println(u.Hostname()) //example.org u, err = url.Parse("https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:17000") //IPV6
if err != nil {
log.Fatal(err)
}
fmt.Println(u.Hostname())//2001:0db8:85a3:0000:0000:8a2e:0370:7334
}
func (*URL) Port
func (u *URL) Port() string
Port 返回 u.Host 的端口部分,不带前导冒号。如果 u.Host 不包含端口,则 Port 返回空字符串。
func (*URL) Parse
func (u *URL) Parse(ref string) (*URL, error)
Parse方法以u为上下文来解析一个URL,ref可以是绝对或相对URL。
本方法解析失败会返回nil, err;否则返回结果和ResolveReference一致。
举例:
package main
import(
"fmt"
"net/url"
"log"
) func main() {
base, err := url.Parse("http://example.com/directory/")
if err != nil {
log.Fatal(err)
}
fmt.Println(base)
result, err := base.Parse("./search?q=dotnet")
if err != nil {
log.Fatal(err)
}
fmt.Println(result)
}
返回:
bogon:~ user$ go run testGo.go
http://example.com/directory/
http://example.com/directory/search?q=dotnet
func (*URL) ResolveReference
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来得到其的绝对路径:
package main
import(
"fmt"
"net/url"
"log"
) func main() {
//该相对路径的意思是
u, err := url.Parse("../../..//search?q=dotnet")//相对路径的不同会影响返回的结果
if err != nil {
log.Fatal(err)
}
fmt.Println(u)
base, err := url.Parse("http://example.com/directory/")
if err != nil {
log.Fatal(err)
}
fmt.Println(base)
fmt.Println(base.ResolveReference(u))
}
返回:
bogon:~ user$ go run testGo.go
../../..//search?q=dotnet
http://example.com/directory/
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)
func (u *URL) MarshalBinary() (text []byte, err error)
举例:
package main
import(
"fmt"
"net/url"
"log"
"reflect"
) func main() {
u, _ := url.Parse("https://example.org")
b, err := u.MarshalBinary() //将其转成二进制
if err != nil {
log.Fatal(err)
}
fmt.Println(reflect.TypeOf(b)) //[]uint8
fmt.Println(b) //[104 116 116 112 115 58 47 47 101 120 97 109 112 108 101 46 111 114 103]
fmt.Printf("%s\n", b) //https://example.org
}
func (*URL) UnmarshalBinary
func (u *URL) UnmarshalBinary(text []byte) error
举例:
package main
import(
"fmt"
"net/url"
"log"
"reflect"
) func main() {
u := &url.URL{}
//将其从二进制转成url.URL类型
err := u.UnmarshalBinary([]byte("https://example.org:8000/foo"))
if err != nil {
log.Fatal(err)
}
fmt.Println(reflect.TypeOf(u)) //*url.URL
fmt.Println(u) //https://example.org:8000/foo
fmt.Println(u.Hostname()) //example.org
fmt.Println(u.Port()) // }
type Userinfo
type Userinfo struct {
// 内含隐藏或非导出字段
}
Userinfo类型是一个URL的用户名和密码细节的一个不可修改的封装。一个真实存在的Userinfo值必须保证有用户名(但根据 RFC 2396可以是空字符串)以及一个可选的密码。
func User
func User(username string) *Userinfo
User函数返回一个用户名设置为username的不设置密码的*Userinfo。
func UserPassword
func UserPassword(username, password string) *Userinfo
UserPassword函数返回一个用户名设置为username、密码设置为password的*Userinfo。
这个函数应该只用于老式的站点,因为风险很大,不建议使用,参见RFC 2396。
func (*Userinfo) Username
func (u *Userinfo) Username() string
Username方法返回用户名。
func (*Userinfo) Password
func (u *Userinfo) Password() (string, bool)
如果设置了密码返回密码和真,否则会返回假。
func (*Userinfo) String
func (u *Userinfo) String() string
String方法返回编码后的用户信息,格式为"username[:password]"。
举例:
package main
import(
"fmt"
"net/url"
"log"
) func main() {
u := &url.URL{
Scheme: "https",
User: url.UserPassword("me", "pass"),
Host: "example.com",
Path: "foo/bar",
RawQuery: "x=1&y=2",
Fragment: "anchor",
}
fmt.Println(u.User.Username()) //me
password, b := u.User.Password()
if b == false{
log.Fatal("can not get password")
}
fmt.Println(password) //pass
fmt.Println(u.User.String()) //me:pass }
type Values
type Values map[string][]string
Values将建映射到值的列表。它一般用于查询的参数和表单的属性。不同于http.Header这个字典类型,Values的键是大小写敏感的。
func ParseQuery
func ParseQuery(query string) (m Values, err error)
ParseQuery函数解析一个URL编码的查询字符串,并返回可以表示该查询的Values类型的字典。本函数总是返回一个包含了所有合法查询参数的非nil字典,err用来描述解码时遇到的(如果有)第一个错误。
举例:
package main
import(
"fmt"
"net/url"
"log"
) func main() {
v, err := url.ParseQuery("friend=Jess&friend=Sarah&fruit=apple&name=Ava")
if err != nil {
log.Fatal(err)
}
fmt.Println(v) //map[friend:[Jess Sarah] fruit:[apple] name:[Ava]]
}
func (Values) Get
func (v Values) Get(key string) string
Get会获取key对应的值集的第一个值。如果没有对应key的值集会返回空字符串。获取值集请直接用map。
func (Values) Set
func (v Values) Set(key, value string)
Set方法将key对应的值集设为只有value,它会替换掉已有的值集。
func (Values) Add
func (v Values) Add(key, value string)
Add将value添加到key关联的值集里原有的值的后面。
func (Values) Del
func (v Values) Del(key string)
Del删除key关联的值集。
func (Values) Encode
func (v Values) Encode() string
Encode方法将v编码为url编码格式("bar=baz&foo=quux"),编码时会以键进行排序。
举例:
package main
import(
"fmt"
"net/url"
) func main() {
v := url.Values{}
v.Set("name", "Ava")
v.Add("friend", "Jess")
v.Add("friend", "Sarah")
v.Add("fruit", "apple") fmt.Println(v.Get("name"))
fmt.Println(v.Get("friend"))
fmt.Println(v["friend"])
fmt.Println(v.Encode()) v.Del("name")
fmt.Println(v.Encode())
}
返回:
bogon:~ user$ go run testGo.go
Ava
Jess
[Jess Sarah]
friend=Jess&friend=Sarah&fruit=apple&name=Ava
friend=Jess&friend=Sarah&fruit=apple
go标准库的学习-net/url的更多相关文章
- go标准库的学习-net/http
参考:https://studygolang.com/pkgdoc 概念解释: request:用户请求的信息,用来解析用户的请求信息,包括post.get.cookie.url等信息 respons ...
- go标准库的学习-database/sql
参考:https://studygolang.com/pkgdoc 导入方式: import "database/sql" sql包提供了保证SQL或类SQL数据库的泛用接口. 使 ...
- go标准库的学习-crypto/md5
参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/md5" md5包实现了MD5哈希算法,参见RFC 1321. Con ...
- go标准库的学习-crypto/sha1
参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha1" sha1包实现了SHA1哈希算法,参见RFC 3174. ...
- go标准库的学习-crypto/sha256
参考:https://studygolang.com/pkgdoc 导入方式: import "crypto/sha256" sha256包实现了SHA224和SHA256哈希算法 ...
- python 标准库基础学习之开发工具部分1学习
#2个标准库模块放一起学习,这样减少占用地方和空间#标准库之compileall字节编译源文件import compileall,re,sys#作用是查找到python文件,并把它们编译成字节码表示, ...
- python calendar标准库基础学习
# -*- coding: utf-8 -*-# 作者:新手__author__ = 'Administrator'#标准库:日期时间基础学习:calendar:处理日期#例1import calen ...
- 《C标准库》学习笔记整理
简介 <C标准库>书中对 C 标准库中的 15 个头文件的内容进行了详细的介绍,包括各头文件设计的背景知识.头文件中的内容.头文件中定义的函数和变量的使用.实现.测试等. 我学习此书的目的 ...
- python linecache标准库基础学习
#python标准库基础之:linecacge:高效读取文本文件#说明与作用"""可以从文件或者导入python模块获取文件,维护一个结果缓存,从而可以更高效地从相同文件 ...
随机推荐
- Java学习笔记之——类与对象
1.参数的传递方式 1)值传递 2)引用传递 2.类和对象: (1)类的定义: public class 类名{ 类型 属性1: 类型 属性2: ……… public 返回值类型 方法名1(形参){ ...
- IDEA出现Cannot resolve symbol "xxx"(无法解析符号)
在导入一些包的时候出现报错 1.File->Invalidate Caches/Restart 清除缓存并重启 idea2.检查pom文件中的依赖关系是否正确3.maven -> Reim ...
- Spring基于XML方式的使用
一.IoC配置 IoC的配置是通过Spring的xml文件的bean标签进行的. 1.bean标签介绍 bean标签一般是在xml文件进行配置的,xml文件一般样式如下: <?xml versi ...
- (三)Sass和Compass--制作精灵图片
6.1 精灵的工作原理 // 将各种图片合并到一张图片里面,并在不同的状态下改变背景图片的位置; 6.2 精灵的重要性 // 压缩图片的内存; // 减少HTTP请求 6.2.3 Compass处理精 ...
- Python全栈学习_day006作业
Day6作业及默写 ,使用循环打印以下效果: : * ** *** **** ***** : ***** **** *** ** * : * *** ***** ******* ********* . ...
- json&pickle数据序列化模块
用于序列化的模块 json,通用的序列化方式,序列化成为str类型,支持所有语言识别,序列化的数据具有局限性. pickle,python的所有数据类型都可以被序列化,序列化为bites格式,只适用于 ...
- 【读书笔记】iOS-UDID
UIDevice类可以返回当前iOS设备的UDID,以前开发者通常使用UDID作为识别每台设备的唯一标识,然后从iOS5开始,苹果公司将这一功能标记为废止并不推荐使用,苹果公司在iOS6之后将这个功能 ...
- 异步陷阱之IO篇
很多教程和资料都强调流畅的用户体验需要异步来辅助,核心思想就是保证用户前端的交互永远有最高的优先级,让一切费时的逻辑通通放到后台,等到诸事完备,通知一下前端给个提示或者继续下一步.随着.NET发展,a ...
- LoadRunner11录制脚本出现的问题
问题一:无法启动IE浏览器 原因:设置录制程序的录制填写错误,因为IE有两个一个是32位的一个是64位的 我们需要设置浏览器为IE 32位即可正常运行 问题二:无法录制百度等官网页面 原因:录制选项中 ...
- Android清单文件合并的那些事
APK文件只能包含一个AndroidManifest.xml文件,但Android Studio项目可以包含多个文件(通过buildSrc.导入的库引入).因此,在构建应用时,Gradle构建会将所有 ...