Cookie值含空格等特殊字符必须URL编码,否则浏览器解析出错;Go侧用url.QueryEscape编码、c.SetCookie写入,读取时自动解码;JS侧需encodeURIComponent写入、decodeURIComponent读取,避免双重编码。

Cookie值直接写空格会出问题
不能。浏览器在解析 Set-Cookie 响应头时,会把未编码的空格、分号、逗号、等号、双引号等当作分隔符或语法边界,导致值被截断或整个 Cookie 被忽略。比如 c.SetCookie(&http.Cookie{Name: "user", Value: "Alice Smith"}),浏览器实际只收到 "Alice",后面丢弃。
- 必须用
url.QueryEscape(Go 侧)或encodeURIComponent(JS 侧)对Value单独编码 -
Name(键名)建议只用 ASCII 字母/数字/下划线,不强制编码;但若含特殊字符(如点、中划线),也应同样编码 - 编码只作用于值本身,不要对整个
"key=value"字符串编码 - 读取后必须用
url.QueryUnescape(Go)或decodeURIComponent(JS)解码,否则看到的是 %E5%BC%A0%E4%B8%89 这类乱码
Go Echo 中写带中文/空格的 Cookie 正确姿势
用 c.SetCookie() 时,Value 字段必须是已编码的字符串;框架不会帮你做这一步。常见错误是传入原始中文字符串,结果浏览器存的是乱码或空值。
- 写入前:
val := url.QueryEscape("张三 123"),再构造&http.Cookie{Value: val, ...} - 读取后:
cookie, _ := c.Cookie("user"); rawVal := cookie.Value; decoded, _ := url.QueryUnescape(rawVal) - 注意:
http.Cookie.MaxAge和Expires不要同时设,否则部分浏览器可能忽略过期逻辑 - 如果值里有换行、制表符等不可见字符,
url.QueryEscape同样能处理,但建议业务层先 trim 或校验
JavaScript 侧读写要配对解码
前端用 document.cookie 写入时,若没编码就塞中文或空格,浏览器可能静默失败或只存一半。更隐蔽的问题是:后端 Echo 用 c.Cookie() 读到的是已解码后的原始值(框架自动调了 url.QueryUnescape),而 JS 手动读取时拿到的是原始编码串,容易误判“前后端值不一致”。
- 写入:
document.cookie = "user=" + encodeURIComponent("李四 456") + "; path=/" - 读取:先按分号分割,再对 value 部分调
decodeURIComponent,不能直接用正则匹配完就用 - 避免用
unescape()—— 它不支持 UTF-8,已废弃 - 如果后端返回的是
Set-Cookie: user=%E6%9D%8E%E5%9B%9B+456,注意+在 URL 编码中代表空格,但decodeURIComponent会正确还原,无需额外替换
为什么不用 http.SetCookie?
直接调 http.SetCookie(c.Response(), cookie) 会绕过 Echo 的 Header 管理机制,和 c.SetCookie() 冲突。轻则 Cookie 写不进响应头,重则触发 header wrote after xxx panic。
- Echo 的
c.SetCookie()是唯一受支持的写法,它确保 Header 操作在 WriteHeader 之前完成 -
c.Cookie("name")返回的是已自动解码后的值;若想跳过解码看原始字节,得从c.Request().Header["Cookie"]手动解析(不推荐) - 所有中间件(如日志、CORS)都依赖 Echo 封装的 Cookie 接口,手动操作会让它们“看不见”你写的 Cookie
真正容易被忽略的是:编码/解码必须成对出现在同一侧(Go 或 JS),且只作用于 Value。很多人在 Go 里写了 QueryEscape,又在 JS 里多套一层 encodeURIComponent,结果值变成双重编码,怎么解都错。










