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 '#'
}

URL结构表示解析之后的URL,一般格式为:

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

由于path和query部分只能使用大小写字母、数字以及有限的几个特殊标点,其它所有的字符都需要进行URL编码:百分号+2位16进制数。例如,空格被编码为"%20",斜线被编码为"%2f",有时候query的value中空格会被编码为"+"。

例如,query部分被编码后的内容如下:

name=Hiram%20Veeblefeetzer&age=35&country=Madagascar+abc

它表示3个key/value:name="Hiram Veeblefeetzer"age=35country=Madagascar abc

关于URL,其中:

  • Host字段是包含host和port两部分的,如果需要分别返回host、port,使用URL.HostnameURL.Port
  • User字段包含了Username和Password,要分别返回它们,使用URL.User.Username()URL.User.Password()
  • Path字段表示解码后的URL路径,也就是不带"%"的普通字符串路径
  • RawPaht字段表示编码后的安全路径,即带上了"%"的路径
  • RawQuery字段表示编码后的Query,即打上了"%"的query字符串,它包含了所有key/value,要分离每个key/value,使用ParseQuery()方法将它们解析到一个map中

URL解析示例

使用URL的Parse(string)方法可以将字符串构造成一个URL对象,并返回这个URL对象的指针。

现在使用这个方法来构造一个URL对象,并解析其中的各个部分:

package mainimport "fmt"
import "net/url"func main() {// 将字符串构造成URL对象s := "postgres://user:pass@host.com:5432/path?k=v#f"u, err := url.Parse(s)if err != nil {panic(err)}// 获取schema部分fmt.Println(u.Scheme)// User字段包含了Username和Password,需要分别获取fmt.Println(u.User)fmt.Println(u.User.Username())p, _ := u.User.Password()fmt.Println(p)// Host字段包含了hostname和portfmt.Println(u.Host)fmt.Println(u.Hostname())fmt.Println(u.Port())// 取得Path和Fragment字段fmt.Println(u.Path)fmt.Println(u.Fragment)// 取得query的key/value// 要取出各个key/value,使用ParseQuery()将RawQuery字段解析成map// key是字符串,value是字符串的slice,如果有key相同,则多个值放进这个slicefmt.Println(u.RawQuery)m, _ := url.ParseQuery(u.RawQuery)fmt.Println(m)fmt.Println(m["k"][0])
}

结果:

postgres
user:pass
user
pass
host.com:5432
host.com
5432
/path
f
k=v
map[k:[v]]
v

构造URL

URL的Parse(string)方法可以将字符串构造成一个URL对象,URL的String()方法可以返回编码后的URL值。

例如:

urlstr := "http://www.cnblogs.com/f-ck-need-u"
myurl,_ := url.Parse(urlstr)
fmt.Println(myurl.String())

输出:

http://www.cnblogs.com/f-ck-need-u

由于URL的path和query部分可能包含特殊字符,直接使用纯字符串构造URL会不安全。应该使用另外两个函数将普通字符转换成编码后的字符:

func PathEscape(s string) string
func QueryEscape(s string) string

再将编码之后的path和query作为Parse()方法的一部分。

例如:

package mainimport ("fmt""net/url"
)func main() {// 要构造:http://www.example.int/下// Path: search// Query: food=pie aaa//        action=like// 的URLs := "http://www.example.int"p := "search"path := url.PathEscape(p)// query部分qfood := "pie aaa"qaction := "like"qqfood := url.QueryEscape(qfood)qqaction := url.QueryEscape(qaction)// 将query组合起来query := "food=" + qqfood + "&action=" + qqaction// 构造urlmyurlstr := s + "/" + path + "?" + querymyurl, err := url.Parse(myurlstr)if err != nil {panic(err)}// 解析URLfmt.Println(myurl.String())// 解析url的query部分fmt.Println(myurl.RawQuery)qmaps, _ := url.ParseQuery(myurl.RawQuery)fmt.Println(qmaps["food"])fmt.Println(qmaps["action"])
}

这很麻烦,对于Query部分,更好的方法是使用Values.Encode()方法,见后文。

url Path部分

在URL结构中:有Path和RawPath两个字段

type URL struct{...Path     string    // path (relative paths may omit leading slash)RawPath  string    // encoded path hint (see EscapedPath method)...
}

其中Path是解码后的路径,RawPath是编码后的路径。

前面解释了PathEscape()函数,它是将字符串转换为编码后的字符串,可以直接将编码后的结果作为构造url的path部分,这样是最安全的构造方式。

除此之外,还有一个EscapePath()方法:如果RawPath存在且有效,则直接返回RawPath字段的值,如果不存在,则EscapePath()自己计算一个编码后的路径。

URL.String()方法是直接调用EscapePath()来构造路径部分的。

Userinfo

type Userinfofunc User(username string) *Userinfofunc UserPassword(username, password string) *Userinfofunc (u *Userinfo) Password() (string, bool)func (u *Userinfo) String() stringfunc (u *Userinfo) Username() string

User()函数构造一个Userinfo,但只包含Username不包含password。

UserPassword()函数构造一个Userinfo,包含Username和password,但因为明文显示,不建议使用。

String()返回"username[:password]"格式的username和Password。

Username()和Password()分别返回对应的部分。

Query部分

URL结构中有一个RawQuery字段:

type URL struct {...RawQuery string...
}

RawQuery字段是编码后的query。

有几个方法:

func (u *URL) Query() Values

它读取RawQuery字段的值并返回Values类型。但会直接丢弃错误或畸形的query部分,如果要检查错误或畸形,使用ParseQuery()函数。

注意上面Query()的返回值是Values类型,它是一个map结构:

type Values map[string][]stringfunc 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)

ParseQuery()函数解析给定字符串query并将query的各个部分填充到返回值类型Values的map结构中,同时会检查错误。

Add()、Del()、Set()和Get()都用来操作Values的map结构,意义都很清晰。唯一需要注意的是,Add()是追加操作,Set()是替换已有值,如果操作的key不存在,则直接创建。

Encode()是将Values中的数据根据key排序后编码成URL的query,且是编码后的query。

下面是一个用法:

package mainimport ("fmt""net/url"
)func main() {s := "http://www.example.int"p := "search"path := url.PathEscape(p)// query部分values := url.Values{}values.Set("food","pie aaa")values.Add("action","like")values.Add("name","abc")values.Add("name","def")values.Add("name","gh")// Encode() == "action=like&food=pie+aaa&name=abc&name=def&name=gh"query := values.Encode()// 构造urlmyurlstr := s + "/" + path + "?" + querymyurl, err := url.Parse(myurlstr)if err != nil {panic(err)}// 解析urlfmt.Println(myurl.String())
}

转载于:https://www.cnblogs.com/f-ck-need-u/p/10020927.html

Go Web:URLs相关推荐

  1. Flutter Web:Shadow Root问题

    document.getElementById找不到节点 在flutter1.x版本的dev分支上可以使用flutter web,但是我们在使用第三方js sdk的时候会出现问题,比如AgoraRtc ...

  2. WEB:Wife_wife

    WEB:Wife_wife use by payload:"__proto__"{"isAdmin":true} get flag CatCTF{test_fl ...

  3. 移动开发中的 Web:WebView、WebKit、JSCore、Web 优化、热修复、跨平台、Native、Hybrid……...

    移动开发领域近年来已经逐渐告别了野蛮生长的时期,进入了相对成熟的时代.而一直以来 Native 和 Web 的争论从未停止,通过开发者孜孜不倦的努力,Web 的效率和 Native 的体验也一直在寻求 ...

  4. web:H5和小程序的区别

    web:H5和小程序的区别 H5和小程序的区别 H5和小程序不具备可比性,只是很多移动端的场景下,两种选择都能实现产品的大部分功能.最近几年,小程序的兴起,让人们理解他等同于H5,其实不然. 关于小程 ...

  5. 美团开源Logan Web:前端日志在Web端的实现

    来自:美团技术团队 2018 年,美团点评推出大前端日志系统-- Logan,并开源了 Android 与 iOS 端的 SDK.这次,我们又开源了在 Web 环境运行的 SDK.日志分析平台以及服务 ...

  6. java web filter标签是什么,Java Web:5.Filter

    目录 什么是Filter? Filter是由Servlet容器进行调用,对 Servlet容器请求java服务端程序(调用资源:JSP,Servlet,静态HTML),java服务端程序响应Servl ...

  7. Go Web:HttpRouter路由(一)

    2019独角兽企业重金招聘Python工程师标准>>> HttpRouter是一个轻量级但却非常高效的multiplexer. 手册: https://godoc.org/githu ...

  8. Web:你知道我这十几年是怎么过来的吗?!

    大家好,我是若川.持续组织了8个月源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构系列& ...

  9. 美团开源 Logan Web:前端日志在 Web 端的实现

    1.前言 Logan 是美团点评推出的大前端日志系统,支持多端环境运行,可为客户端.Web.小程序等用户端环境提供前端日志的存储.收集.上报及分析能力,能够帮助开发人员快速定位并解决端上问题,便于及时 ...

最新文章

  1. 从将机器学习模型转化成真正产品和服务中学到的经验教训
  2. 【CocoaPods】CocoaPods:Objective-C依赖库管理(XCode 4.6)
  3. mysql 立方根函数_PostgreSQL基础知识之SQL操作符实践指南
  4. 计量经济学第六版计算机答案,伍德里奇计量经济学导论计算机习题第六章第13题c_6.13...
  5. 132_Power BI之建模必备要素Power Query之数据表字段名称管理
  6. Java中,成员内部类的常见修饰符及应用 成员内部类不是静态的,访问的格式...
  7. 佳能Canon PIXMA G1010 打印机驱动
  8. git可视化工具Sourcetree使用全攻略(包括各种git冲突解决)
  9. Delphi7--基本数据类型和表达式
  10. 图的深度优先遍历及广度优先遍历
  11. 利用计算机为祖国做贡献的人,李晓维:祖国,我把科研事业献给您
  12. Benchmark 第一篇 了解Benchmark
  13. Android开发者跳槽面试,Android面试题及解析
  14. NMAP手册中文版(附英文解释版)
  15. 计算机网络中常见的交换机和路由器的品牌
  16. linux下rz和sz命令实现上传下载文件
  17. red flag 5.0 安装
  18. Echarts 地图概述及二维地图初始化
  19. Java编程语言是什么 JAVA有什么优势
  20. ecstore mysql_ECStore最新开源版5.0.1下载

热门文章

  1. KVM虚拟化笔记(七)------kvm虚拟机VNC的配置
  2. subprocess installed post-installation script returned error exit status 127
  3. 'staticfiles' is not a registered tag library. Must be one of:
  4. 对select的结果进行count统计
  5. SVC调参总结+调参实例
  6. 固态+机械(uefi类型的bios),用easybcd安装win10+ubuntu16.04双系统
  7. 正态分布的前世今生(一)
  8. 对计算机课评价,信息技术课教学效果评价
  9. 爱宠无人看护?别担心人工智能已经来了
  10. JPA关系映射系列一:one-to-one外键关联