Go的http.ParseCookie仅解析单个"name=value"格式Cookie,不支持分号分隔的完整字符串;正确做法是手动split分号、trim空格、url.QueryUnescape解码值。

Go 的 http.ParseCookie 无法直接解析分号分隔的原始 Cookie 字符串
很多人误以为 http.ParseCookie 能处理像 "a=1; b=2; c=hello%20world" 这样的字符串,但它实际只接受单个 Cookie 的 name=value 形式(比如 "a=1"),传入带分号的整串会直接返回 ErrInvalidCookie。这是最常踩的坑——函数名有误导性,它不解析 HTTP 请求头里的完整 Cookie 字段,而是解析单个 Cookie 的键值对。
真正该用的是 http.ReadSetCookie 或手动拆分 + URL 解码,但注意:http.ReadSetCookie 是为 Set-Cookie 响应头设计的,对客户端发来的 Cookie 请求头兼容性差(比如不处理空格、忽略部分属性)。所以生产环境更推荐手动解析。
手动解析:用 strings.Split 拆分后逐个 url.QueryUnescape
标准做法是先按分号切分,再对每个片段做 strings.TrimSpace 和 url.QueryUnescape,最后用 = 分割键值。注意几个关键点:
- 分号后可能有空格(如
"a=1; b=2"中的" b=2"),必须TrimSpace - 值可能被 URL 编码(如
c=hello%20world),必须用url.QueryUnescape,不能用url.PathUnescape - 同一个 key 可能出现多次(虽然少见),按 HTTP 规范应取第一个,但业务可自行决定策略
示例代码片段:
立即学习“go语言免费学习笔记(深入)”;
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
import (
"net/url"
"strings"
)
func parseCookieString(cookieStr string) map[string]string {
cookies := make(map[string]string)
for _, part := range strings.Split(cookieStr, ";") {
part = strings.TrimSpace(part)
if part == "" {
continue
}
if idx := strings.Index(part, "="); idx > 0 {
key := strings.TrimSpace(part[:idx])
val := strings.TrimSpace(part[idx+1:])
if unescaped, err := url.QueryUnescape(val); err == nil {
cookies[key] = unescaped
} else {
cookies[key] = val // 解码失败时保留原样,避免丢数据
}
}
}
return cookies
}
提取特定 key 时别忽略大小写和空格边界
Cookie key 是大小写敏感的(HTTP 协议未规定,但主流服务端和浏览器都区分),且 key 前后空格必须严格匹配。比如 " AuthToken = abc123" 中的 key 实际是 " AuthToken "(含空格),不是 "AuthToken"。常见错误是直接用 map[key] 查找却没清理 key 的空格。
安全做法是:提取前对 key 做 strings.TrimSpace,查找时也用清理后的 key。
- 不要写
cookies["session_id"],先做key := strings.TrimSpace("session_id") - 如果业务允许模糊匹配(如忽略下划线/短横),需额外标准化逻辑,但默认不应这么做
- 值里可能含控制字符或 Unicode,
url.QueryUnescape已处理,无需额外过滤
性能与边界场景:超长 Cookie、恶意分号、无等号片段
真实请求中 Cookie 字符串可能长达几 KB,或包含攻击性输入(如 "a=1;;b=2; ;c=3" 或 "no-equals-here; d=4")。手动解析时要防御这些:
- 空片段(连续分号)必须跳过,否则
part[:idx]会 panic - 无
=的片段(如"HttpOnly")应忽略,它是 Cookie 属性,不是键值对 - 单个 key 长度建议限制(如
- 不做递归解码(如
%2520是%20的编码),url.QueryUnescape默认只解一层
复杂点往往不在解析逻辑本身,而在于你是否假设了输入“干净”。线上流量里永远有少打一个引号、多一个空格、或故意构造的畸形 Cookie。别省那几行防御代码。

















