Go 学习笔记(50)— Go 标准库之 net/url(查询转义、查询参数增/删/改/查、解析URL)

1. URL 概述

import "net/url"

url 包解析 URL 并实现了查询的转码。URL 提供了一种定位因特网上任意资源的手段,但这些资源是可以通过各种不同的方案(比如 HTTPFTPSMTP )来访问,因此 URL 语法会随着方案的不同而不同。

完整的 URL 格式为:

<schema>://<user>:<password>@<host>:<port>/<path>:<params>?<query>#<frag>

各部分字段说明:

  • scheme : 方案是如何访问指定资源的主要标识符,他会告诉负责解析 URL 应用程序应该使用什么协议;
  • user :用户名;
  • password :密码;
  • host : 主机组件标识了因特网上能够访问资源的宿主机器,可以有主机名或者是 IP 地址来表示;
  • port : 端口标识了服务器正在监听的网络端口。默认端口号是 80;
  • path : URL 的路径组件说明了资源位于服务器的什么地方;
  • params : URL 中通过协议参数来访问资源,比名值对列表,分号分割来进行访问;
  • query : 字符串是通过提问问题或进行查询来缩小请求资源类的范围;
  • frag : 为了引用部分资源或资源的一个片段,比如 URL 指定 HTML 文档中一个图片或一个小节;

HTTP 通常只处理整个对象,而不是对象的片段,客户端不能将片段传送给服务器。浏览器从服务器获取整个资源之后,会根据片段来显示你感兴趣的片段部分。

2. 主要类型和函数

2.1 type URL

GoURL 结构体如下:

type URL struct {
    Scheme   string    //具体指访问服务器上的资源使用的哪种协议
    Opaque   string    // 编码后的不透明数据
    User     *Userinfo // 用户名和密码信息,有些协议需要传入明文用户名和密码来获取资源,比如 FTP
    Host     string    // host或host:port,服务器地址,可以是 IP 地址,也可以是域名信息
    Path     string  //路径,使用"/"分隔
    RawPath    string    // 已编码的路径提示(参见EscapedPath方法)
	ForceQuery bool      // 添加一个查询('?'),即使RawQuery为空
    RawQuery string // 编码后的查询字符串,没有'?'
    Fragment string // 引用的片段(文档位置),没有'#'
}

示例代码:

func main() {
	urlString := "https://admin:passwd@www.baidu.com:80/search?mq=test#12345"
	u, err := url.Parse(urlString)
	if err != nil {
		fmt.Println("parse error ", err)
	}
	fmt.Printf("u type is %T, u is %#v\n", u, u)
	/*
		u type is *url.URL,
		u is &url.URL{
			Scheme:"https", Opaque:"", User:(*url.Userinfo)(0xc000088150),
			Host:"www.baidu.com:80", Path:"/search", RawPath:"", ForceQuery:false,
			RawQuery:"mq=test", Fragment:"12345"
		}

	*/
	fmt.Printf("u.Scheme is %#v\n", u.Scheme) // u.Scheme is "https"
	fmt.Printf("u.Opaque is %#v\n", u.Opaque) // u.Opaque is ""
	fmt.Printf("u.User is %#v\n", u.User)
	// u.User is &url.Userinfo{username:"admin", password:"passwd", passwordSet:true}

	fmt.Printf("u.Host is %#v\n", u.Host)             // u.Host is "www.baidu.com:80"
	fmt.Printf("u.Path is %#v\n", u.Path)             // u.Path is "/search"
	fmt.Printf("u.RawPath is %#v\n", u.RawPath)       // u.RawPath is ""
	fmt.Printf("u.ForceQuery is %#v\n", u.ForceQuery) // u.ForceQuery is false
	fmt.Printf("u.RawQuery is %#v\n", u.RawQuery)     // u.RawQuery is "mq=test"
	fmt.Printf("u.Fragment is %#v\n", u.Fragment)     // u.Fragment is "12345"

}

2.1.1 func Parse

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

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

2.1.2 func ParseRequestURI

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

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

func main() {
	urlString := "https://admin:passwd@www.baidu.com:80/search?mq=test#12345"
	u, err := url.ParseRequestURI(urlString)
	if err != nil {
		fmt.Println("parse error ", err)
	}
	fmt.Printf("u.Fragment is %#v\n", u.Fragment) // u.Fragment is ""

}

2.1.3 func (*URL) IsAbs

func (u *URL) IsAbs() bool

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

2.1.4 func (*URL) Query

func (u *URL) Query() Values

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

2.1.5 func (*URL) RequestURI

func (u *URL) RequestURI() string

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

2.1.6 func (*URL) String

func (u *URL) String() string

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

2.1.7 func (*URL) Parse

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

Parse 方法以 u 为上下文来解析一个 URLref 可以是绝对或相对 URL 。本方法解析失败会返回 nil , err ;否则返回结果和 ResolveReference 一致。

func main() {
	u, _ := url.Parse("http://example.com/dir/")
	fmt.Println(u) // http://example.com/dir/

	result, _ := u.Parse("./search?mq=rabbitmq")
	fmt.Println(result) // http://example.com/dir/search?mq=rabbitmq
}

2.1.8 func (*URL) ResolveReference

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

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

2.1.9 代码示例

func main() {
	urlString := "https://www.baidu.com/search?mq=rabbitmq&queue=people#12345"
	u, err := url.Parse(urlString)
	if err != nil {
		fmt.Println("parse error ", err)
	}
	fmt.Printf("u.IsAbs is %#v\n", u.IsAbs()) // u.IsAbs is true
	fmt.Printf("u.Query is %#v\n", u.Query())
	// u.Query is url.Values{"mq":[]string{"rabbitmq"}, "queue":[]string{"people"}}
	fmt.Printf("u.RequestURI is %#v\n", u.RequestURI())
	// u.RequestURI is "/search?mq=rabbitmq&queue=people"
	fmt.Printf("u.String is %#v\n", u.String())
	// u.String is "https://www.baidu.com/search?mq=rabbitmq&queue=people#12345"

}

2.2 type Values

type Values map[string][]string

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

2.2.1 func ParseQuery

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

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

代码示例:

func main() {
	rawUrl := "mq=rabbitmq&queue=people"
	v, err := url.ParseQuery(rawUrl)
	if err != nil {
		fmt.Println("ParseQuery error ", err)
	}
	fmt.Printf("v type is %T, v is %#v\n", v, v)
	// v type is url.Values, v is url.Values{"mq":[]string{"rabbitmq"}, "queue":[]string{"people"}}

	// 等价于下面的方法
	urlString := "https://www.baidu.com/search?mq=rabbitmq&queue=people#12345"
	u, _ := url.Parse(urlString)
	queryV := u.Query()
	fmt.Printf("queryV type is %T, queryV is %#v\n", queryV, queryV)
	// queryV type is url.Values, queryV is url.Values{"mq":[]string{"rabbitmq"}, "queue":[]string{"people"}}
}

2.2.2 func (Values) Get

func (v Values) Get(key string) string

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

2.2.3 func (Values) Set

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

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

2.2.4 func (Values) Add

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

Addvalue 添加到 key 关联的值集里原有的值的后面。

2.2.5 func (Values) Del

func (v Values) Del(key string)

Del 删除 key 关联的值集。

2.2.6 func (Values) Encode

func (v Values) Encode() string

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

2.2.7 代码示例

func main() {
	rawUrl := "mq=rabbitmq&queue=people"
	v, err := url.ParseQuery(rawUrl)
	if err != nil {
		fmt.Println("ParseQuery error ", err)
	}
	fmt.Printf("v type is %T, v is %#v\n", v, v)
	// v type is url.Values, v is url.Values{"mq":[]string{"rabbitmq"}, "queue":[]string{"people"}}

	fmt.Println(v.Get("mq")) // rabbitmq
	v.Set("mq", "redis")
	fmt.Println(v.Get("mq")) // redis
	v.Add("name", "wohu")
	fmt.Printf("v is %#v\n", v)
	// v is url.Values{"mq":[]string{"redis"}, "name":[]string{"wohu"}, "queue":[]string{"people"}}

	fmt.Printf("v.Encode is %#v\n", v.Encode()) // v.Encode is "mq=redis&name=wohu&queue=people"
	v.Del("name")
	fmt.Printf("v is %#v\n", v)
	// v is url.Values{"mq":[]string{"redis"}, "queue":[]string{"people"}}
}
package main
    import (
        "fmt"
        "net/url"
  
    )
    func main()  {
        v := url.Values{}
        //公共参数
        v.Add("Name", "wohu")
        v.Add("Age", "18")
        fmt.Println( v )
    }

2.3 查询转义

2.3.1 func QueryEscape

func QueryEscape(s string) string

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

2.3.2 func QueryUnescape

func QueryUnescape(s string) (string, error)

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

2.3.3 代码示例

func main() {
	rawUrl := "mq=rabbitmq&queue=people"
	stdUrl := url.QueryEscape(rawUrl)
	fmt.Printf("stdUrl is %v\n", stdUrl) // stdUrl is mq%3Drabbitmq%26queue%3Dpeople
	rawurl, _ := url.QueryUnescape(stdUrl)
	fmt.Printf("rawurl is %v\n", rawurl) // rawurl is mq=rabbitmq&queue=people
}

参考:
https://www.cnblogs.com/wanghui-garcia/p/10424463.html
https://studygolang.com/static/pkgdoc/pkg/net_url.htm

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值