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. Teradata Delete Database and Drop Database

    DELETE DATABASE and DELETE USER statements delete all data tables, views, and macros from a database ...

  2. RabbitMQ 适用于云计算集群的远程调用(RPC)

    在云计算环境中,很多时候需要用它其他机器的计算资源,我们有可能会在接收到Message进行处理时,会把一部分计算任务分配到其他节点来完成.那么,RabbitMQ如何使用RPC呢?在本篇文章中,我们将会 ...

  3. day_3各种数据类型与各种运算符

    首先我们复习一下昨天的内容 1:语言的分类: --有三种 机器语言,汇编语言,高级语言 运行的效率是机器语言最高  开发效率 是高级语言最高 2:计算机由五大部分组成:控制器+运算器+存储器+inpu ...

  4. 打开xmind 8 输入序列号

    XAka34A2rVRYJ4XBIU35UZMUEEF64CMMIYZCK2FZZUQNODEKUHGJLFMSLIQMQUCUBXRENLK6NZL37JXP4PZXQFILMQ2RG5R7G4QN ...

  5. C语言窗口例子

    #include <windows.h> LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ) ; //声明用来处理消息的函数 in ...

  6. 工作jQuery基础复习(一)

    1.prop() 方法 设置或者返回被选元素的属性和值 当该方法用于返回属性值时,则返回第一个匹配元素的值 当该方法设定属性值时,则为匹配元素集合设置一个或者多个属性/值对

  7. python jieba库的基本使用

    第一步:先安装jieba库 输入命令:pip install jieba jieba库常用函数: jieba库分词的三种模式: 1.精准模式:把文本精准地分开,不存在冗余 2.全模式:把文中所有可能的 ...

  8. 怎样在mybatis里向mysql中插入毫秒数的时间?

    由于业务场景需求,需要记录精准的时间,但是呢,又不要想使用int类型来存储时间,因为这样的可读性比较差了. 怎样在mybatis中向数据库插入毫秒级别的时间呢? 首先,先来看看怎样向数据库中插入毫秒时 ...

  9. cookie和session的个人理解

    这是我学习后的个人理解  欢迎提点 如果说的不是很正确请纠正 COOKIE: 1.服务端给浏览器客户端返回一个编号(COOKIE值) 2.这个值存在浏览器中,接下来浏览器再次访问我的时候,会把这个值带 ...

  10. Ubuntu 16.04安装下HTK--亲测ok

    1.首先需要安装一些32位库sudo apt-get install libx11-dev:i386 libx11-dev sudo apt-get install g++-multilib sudo ...