在Golang的后端开发中,URL的处理是非常高频的需求,无论是Web服务接收请求参数,还是调用第三方接口拼接请求地址,都需要对URL进行解析、修改、编码等操作。Golang的标准库net/url提供了完整的URL处理能力,不需要引入第三方依赖就能完成大部分URL相关的操作。

net/url核心结构体介绍
net/url库中最核心的结构体是URL,它对应一个完整的URL对象,包含了URL的各个组成部分。我们可以通过解析URL字符串得到这个结构体,也可以手动构造这个结构体来生成URL。
URL结构体的主要字段如下:
- Scheme:URL的协议部分,比如http、https、ftp等
- Host:主机地址,包含域名和端口,比如www.ippipp.com:8080
- Path:路径部分,比如/api/user
- RawQuery:原始查询参数字符串,比如name=test&age=18
- Fragment:锚点部分,比如#top
- Query:查询参数的键值对集合,类型是
url.Values,可以方便地对参数进行增删改查
解析URL的基本操作
解析URL最常用的方法是url.Parse,它接收一个URL字符串,返回解析后的URL结构体和可能的错误。如果URL格式不合法,会返回对应的错误信息。
package main
import (
"fmt"
"net/url"
)
func main() {
// 待解析的URL字符串
rawURL := "https://www.ipipp.com:8080/api/user?id=1001&name=张三#info"
// 解析URL
parsedURL, err := url.Parse(rawURL)
if err != nil {
fmt.Println("解析URL失败:", err)
return
}
// 打印URL各个组成部分
fmt.Println("协议:", parsedURL.Scheme)
fmt.Println("主机:", parsedURL.Host)
fmt.Println("路径:", parsedURL.Path)
fmt.Println("原始查询参数:", parsedURL.RawQuery)
fmt.Println("锚点:", parsedURL.Fragment)
}
运行上面的代码,会输出对应的URL组成部分,我们可以清晰地看到URL被拆分成了不同的字段,方便后续针对性处理。
查询参数的操作
获取到URL结构体后,最常用的操作就是处理查询参数。URL的Query方法会返回一个url.Values类型的对象,我们可以通过这个对象获取、添加、修改、删除查询参数。
获取查询参数
url.Values的Get方法可以获取指定key的第一个值,GetAll方法可以获取指定key的所有值。
package main
import (
"fmt"
"net/url"
)
func main() {
rawURL := "https://www.ipipp.com/api/list?page=1&size=10&sort=time&sort=hot"
parsedURL, _ := url.Parse(rawURL)
// 获取查询参数集合
queryParams := parsedURL.Query()
// 获取单个参数值
page := queryParams.Get("page")
fmt.Println("page参数值:", page)
// 获取多值参数
sortList := queryParams.GetAll("sort")
fmt.Println("sort所有参数值:", sortList)
}
修改和添加查询参数
我们可以直接修改url.Values的内容,然后重新赋值给URL的RawQuery字段,就可以完成查询参数的修改。
package main
import (
"fmt"
"net/url"
)
func main() {
rawURL := "https://www.ipipp.com/api/list?page=1"
parsedURL, _ := url.Parse(rawURL)
queryParams := parsedURL.Query()
// 修改已有参数
queryParams.Set("page", "2")
// 添加新参数
queryParams.Add("size", "20")
// 将修改后的参数重新赋值给URL
parsedURL.RawQuery = queryParams.Encode()
fmt.Println("修改后的URL:", parsedURL.String())
}
URL编码与解码
URL中不能直接包含中文、空格等特殊字符,需要进行编码处理。net/url库提供了QueryEscape和QueryUnescape方法完成编码和解码。
package main
import (
"fmt"
"net/url"
)
func main() {
// 待编码的字符串
rawStr := "张三 18岁"
// URL编码
encodedStr := url.QueryEscape(rawStr)
fmt.Println("编码后:", encodedStr)
// URL解码
decodedStr, _ := url.QueryUnescape(encodedStr)
fmt.Println("解码后:", decodedStr)
}
编码后空格会变成+,中文会变成百分号加十六进制的形式,符合URL的编码规范。解码时可以把编码后的字符串还原成原始内容。
构造URL的方法
除了解析已有的URL,我们也可以手动构造URL结构体来生成新的URL,这种方式可以避免手动拼接字符串导致的格式错误。
package main
import (
"fmt"
"net/url"
)
func main() {
// 手动构造URL结构体
u := &url.URL{
Scheme: "https",
Host: "www.ipipp.com",
Path: "/api/order",
}
// 添加查询参数
params := url.Values{}
params.Add("order_id", "20240501001")
params.Add("status", "paid")
u.RawQuery = params.Encode()
// 生成完整URL字符串
fmt.Println("构造的URL:", u.String())
}
注意事项
- 解析URL时如果传入的字符串不包含协议,
url.Parse不会报错,但Scheme字段会为空,需要根据实际场景判断是否需要补充协议 Query方法每次调用都会重新解析RawQuery,如果频繁操作查询参数,建议先保存Query的返回值再操作,避免重复解析- 修改查询参数后一定要调用
Encode方法再赋值给RawQuery,否则参数中的特殊字符不会被正确编码,导致生成的URL格式错误
net/url库是Golang处理URL的标准方案,覆盖了绝大多数URL处理场景,熟练掌握它的用法可以大幅提升开发效率,减少URL处理相关的bug。