URL也是一个结构体:

type URL struct {
Scheme string
Opaque string // encoded opaque data
User *Userinfo // username and password information
Host string // host or host:port
Path 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 empty
RawQuery 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 main

import "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和port
fmt.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相同,则多个值放进这个slice
fmt.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 main

import (
"fmt"
"net/url"
) func main() {
// 要构造:http://www.example.int/下
// Path: search
// Query: food=pie aaa
// action=like
// 的URL
s := "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 // 构造url
myurlstr := s + "/" + path + "?" + query
myurl, err := url.Parse(myurlstr)
if err != nil {
panic(err)
} // 解析URL
fmt.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 Userinfo
func User(username string) *Userinfo
func UserPassword(username, password string) *Userinfo
func (u *Userinfo) Password() (string, bool)
func (u *Userinfo) String() string
func (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][]string
func ParseQuery(query string) (Values, error)
func (v Values) Add(key, value string)
func (v Values) Del(key string)
func (v Values) Encode() string
func (v Values) Get(key string) string
func (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 main

import (
"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() // 构造url
myurlstr := s + "/" + path + "?" + query
myurl, err := url.Parse(myurlstr)
if err != nil {
panic(err)
} // 解析url
fmt.Println(myurl.String())
}

Go Web:URLs的更多相关文章

  1. Go Web:处理请求

    处理请求 Request和Response http Requset和Response的内容包括以下几项: Request or response line Zero or more headers ...

  2. 未来的 Web:九个不可思议的 WebGL 应用试验

    WebGL 技术允许把 JavaScript 和 OpenGL ES 2.0 结合在一起,通过增加 OpenGL ES 2.0 的一个 JavaScript 绑定,WebGL 可以为 HTML5 Ca ...

  3. web:转盘抽奖

    移动web:转盘抽奖(幸运大转盘)   为了获取客户.回馈客户,平台一般会推出抽奖活动类的营销页.因此web页面中,有各式各样的抽奖效果. 格子式(九宫格),背景滚动式(数字/文字/图案),旋转式(转 ...

  4. 《Mining the Web:Transforming Customer Data into Customer Value》读后札记

    <Mining the Web:Transforming Customer Data into Customer Value> <Web数据挖掘:将客户数据转化为客户价值> — ...

  5. 信息安全-技术-Web:cookie

    ylbtech-信息安全-技术-Web:cookie Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份.进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密 ...

  6. 【Pro ASP.NET MVC 3 Framework】.学习笔记.12.ASP.NET MVC3的细节:URLs,Routing和Areas

    Adam Applied ASP.NET 4 in Context 1 介绍Routing系统 在引入MVC之前,ASP.NET假定被请求的URLs和服务器硬盘上的文件之间有着直接关系.服务器的任务是 ...

  7. 初识WEB:输入URL之后的故事

    1. 概述2. HTTP请求过程3. 相关性能检测及优化手段4. 浏览器的呈现过程5. 浏览器的呈现引擎6. 引用及延伸阅读 概述 为什么输入www.cnblogs.com之后敲一个回车,浏览器就会显 ...

  8. 初识WEB:输入URL之后的故事【转】

    转载一篇文章,分析的是浏览器输入url后所执行的一系列操作!写得非常清晰易懂,分享给大家! 作者:Jesse 出处:http://jesse2013.cnblogs.com/ 本文版权归作者和博客园共 ...

  9. Web:AJAX的详解

    Web中的AJAX技术: 1.介绍:全称:Asnchronous JavaScript and XML,即异步的JavaScript和XML功能:它不是某种编程语言,是一种无需加载整个网页的情况下能够 ...

随机推荐

  1. bootstrap中的dropdown组件扩展hover事件

    bootstrap的下拉组件,需要点击click时,方可展示下拉列表.因此对于喜欢简单少操作的大家来说,点击一下多少带来不便,因此,引入hover监听,鼠标经过自动展示下拉框.其实在bootstrap ...

  2. docker install

    1.安装必要工具集 sudo yum install -y yum-utils 2.安装Docker官方源 sudo yum-config-manager \ --add-repo \ https:/ ...

  3. JSP与Servlet的关系

    之前的文章里有说过,其实Servlet比JSP出现的早,JSP的本质就是Servlet,但是一个是jsp页面,一个是java类,硬要说他们的本质是一样的,搁谁都有点难以置信.后面的结论会更加让你吃惊. ...

  4. msfconlose基本命令

    命令 简介 back 从当前上下文 banner 显示显示一个令人敬畏的metasploit横幅 cd 更改当前工作目录 color 切换颜色 connect 与主机通信 edit 使用$ VISUA ...

  5. day_5字符串和列表的各种操作方法

    字符串类型: 字符串的定义是可以有多种引号嵌套 定义字符串是以开头的引号然后匹配和第一个引号相同的引号,所以当字符串中间出现和第一个引号相同的引号就会出错,这个时候就可以选择别的引号进行创建字符串,或 ...

  6. ZKWeb网页框架2.1正式发布

    2.1.0更新的内容有 更新引用类库 NHibernate 5.1.0 Npgsql 3.2.7 MySqlConnector 0.37.0 Dapper 1.50.4 Dommel 1.10.1 Z ...

  7. 自定义滚动条样式(layui.v1)

    来源于 layui css 代码 ::-webkit-scrollbar { width: 10px; height: 10px; } ::-webkit-scrollbar-button, ::-w ...

  8. 「ZJOI2019」&「十二省联考 2019」题解索引

    「ZJOI2019」&「十二省联考 2019」题解索引 「ZJOI2019」 「ZJOI2019」线段树 「ZJOI2019」Minimax 搜索 「十二省联考 2019」 「十二省联考 20 ...

  9. PostgreSQL查看表、表索引、视图、表结构

    -- 表索引select * from pg_indexes where tablename='person_wechat_label';select * from pg_statio_all_ind ...

  10. JavaScript的文档对象模型DOM

    小伙伴们之前我们讲过很多JavaScript的很多知识点,可以点击回顾一下: <JavaScript大厦之JS运算符>: <JavaScript工作原理:内存管理 + 如何处理4个常 ...