Go 标准库net-url
URL 概述
import "net/url"
url 包解析 URL 并实现了查询的转码。
URL 提供了一种定位因特网上任意资源的手段,但这些资源是可以通过各种不同的方案(比如 HTTP 、 FTP 、 SMTP )来访问,因此 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 通常只处理整个对象,而不是对象的片段,客户端不能将片段传送给服务器。浏览器从服务器获取整个资源之后,会根据片段来显示你感兴趣的片段部分。
主要类型和方法
type URL
Go 中 URL 结构体如下:
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"
}
或者可以利用 URL
结构体构建 url
u := &url.URL{
Scheme: "https",
Host: "www.example.com",
Path: "/path",
RawQuery: "param=value",
}
fmt.Println(u.String()) // 输出: https://www.example.com/path?param=value
func Parse
func Parse(rawurl string) (url *URL, err error)
Parse
方法将原始URL rawurl
解析为URL结构。该URL可以是相对路径,也可以是绝对路径
package main
import (
"fmt"
"net/url"
)
func main() {
urlStr := "https://example.com/path?param1=value1¶m2=value2"
url, err := url.Parse(urlStr)
if err != nil {
fmt.Println("URL解析错误:", err)
return
}
fmt.Println("URL方案:", url.Scheme)
fmt.Println("主机:", url.Host)
fmt.Println("路径:", url.Path)
fmt.Println("查询字符串:", url.RawQuery)
}
结果
URL方案: https
主机: example.com
路径: /path
查询字符串: param1=value1¶m2=value2
这里有个问题,如果 rawurl
是一个没有前面协议( http://
或者 https://
)的字符串,则会报错
需要做一定的处理
```go
u:="127.0.0.1:8000"
// 先去除后缀
u1 := strings.TrimRight(u, "/")
// 然后判断前面是否有协议
if !strings.HasPrefix(u1, "http://") && !strings.HasPrefix(u1, "https://") {
// 添加默认的http://作为协议前缀
u1 = "http://" + strings.TrimSpace(u1)
}
// 然后再转换成URL结构体
parsedURL, err := url.Parse(u1)
if err != nil {
c.log.L().Errorw("url转化失败", err)
os.Exit(1)
}
```
func ParseRequestURI
func ParseRequestURI(rawURL string) (*URL, 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 ""
}
func (*URL) IsAbs
func (u *URL) IsAbs() bool
函数在 URL 是绝对 URL 时才返回真。
func (*URL) Query
func (u *URL) Query() Values
Query
方法解析 RawQuery
字段并返回其表示的 Values 类型键值对。
func (*URL) RequestURI
func (u *URL) RequestURI() string
RequestURI
方法返回编码好的 path?query
或 opaque?query
字符串,用在 HTTP 请求里。
func (*URL) String
func (u *URL) String() string
String
将 URL
重构为一个合法 URL 字符串。
func (*URL) Parse
func (u *URL) Parse(ref string) (*URL, error)
Parse
方法以 u
为上下文来解析一个 URL
, ref
可以是绝对或相对 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
}
func (*URL) ResolveReference
func (u *URL) ResolveReference(ref *URL) *URL
本方法根据一个绝对 URI
将一个 URI
补全为一个绝对 URI
。
参数 ref
可以是绝对 URI
或者相对 URI
。
ResolveReference
总是返回一个新的 URL
实例,即使该实例和 u
或者 ref
完全一样。如果 ref
是绝对 URI
,本方法会忽略参照 URI
并返回 ref
的一个拷贝。
范例
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"
}
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 用来描述解码时遇到的(如果有)第一个错误。
代码示例
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"}}
}
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
编码为 ur
编码格式(“bar=baz&foo=quux”),编码时会以键进行排序。
范例
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 )
}
查询转义
func QueryEscape
func QueryEscape(s string) string
QueryEscape 函数对 s 进行转码使之可以安全的用在 URL 查询里。
func QueryUnescape
func QueryUnescape(s string) (string, error)
QueryUnescape
函数用于将 QueryEscape
转码的字符串还原。
它会把 %AB
改为字节 0xAB
,将 +
改为空格 。
如果有某个 %
后面未跟两个十六进制数字,本函数会返回错误。
范例
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/guangdelw/p/17559766.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示