Cookie值只能是字符串,布尔值需显式转换:写入用strconv.FormatBool(),读取用strconv.ParseBool()并捕获ErrSyntax,禁止混用Cookie与Session存储同一布尔状态。

Cookie 值只能是字符串,不能直接存布尔值
Echo 的 c.SetCookie() 底层调用的是 http.SetCookie(),而 HTTP Cookie 规范(RFC 6265)只允许值为 US-ASCII 字符串,不支持原生布尔、整数或结构体。试图传 true 或 false 会触发类型错误或被强制转成 "true"/"false"(Go 的 fmt.Sprintf("%v", b) 行为),但这种隐式转换不可控且易混淆。
- 直接写
c.SetCookie(&http.Cookie{Name: "logged_in", Value: true})编译失败 ——Value字段类型必须是string - 若手动拼接:
Value: strconv.FormatBool(true),读取时仍需显式转回bool,否则sess.Values["logged_in"]拿到的是"true"字符串,不是true - 前端 JavaScript 读取同名 Cookie 时也会拿到字符串
"true",if (cookie === true)永远为false
安全的布尔型 Cookie 存取模式
必须走「字符串 ↔ 布尔」的显式双向转换,且全程防御空值和非法字符串。推荐封装两个工具函数,避免散落各处的重复逻辑:
- 写入时统一用
strconv.FormatBool():c.SetCookie(&http.Cookie{Name: "active", Value: strconv.FormatBool(isActive), MaxAge: 3600}) - 读取时先用
c.Cookie("active")拿到*http.Cookie,再用strconv.ParseBool(cookie.Value)转换;注意捕获strconv.ErrSyntax - 更稳妥的做法是:只接受
"1"/"0"或"true"/"false"(小写),拒绝"True"、"TRUE"等变体,防止大小写不一致导致解析失败 - 不要依赖
http.Cookie.HttpOnly或Secure字段来“掩盖”类型混乱 —— 它们解决的是传输安全,不是数据语义
和 Session.Values 混用时的典型陷阱
很多人把 Cookie 当 Session 用,比如把 logged_in=true 写进 Cookie,又在 Session 里存一份 sess.Values["logged_in"] = true,结果两边类型不同步:
- Session 里存的是 Go 原生
bool,但 Cookie 里是字符串;某次只更新了 Cookie 没更新 Session,或反之,逻辑就错位 -
sess.Values["flag"]取出后直接断言flag := val.(bool),而实际它可能是从 JSON 解析来的map[string]interface{},底层是json.Number或string,运行时 panic - 正确姿势:Session 和 Cookie 若表示同一语义状态,应只选其一作为单一信源;如必须双写,务必用相同序列化方式(例如都走
json.Marshal()+base64.RawURLEncoding.EncodeToString())
为什么不用 JSON 编码布尔值?
可以,但没必要。对单个布尔值做 json.Marshal(true) 得到 "true",和直接 strconv.FormatBool(true) 结果一样,还多一次内存分配和 error 检查。只有当你要存嵌套结构(如 {"enabled":true,"mode":"dark"})时,JSON 才有意义。
真正容易被忽略的是:Cookie 的 MaxAge 和 Expires 设置一旦为 0 或负数,浏览器会立即删除它,此时 c.Cookie("flag") 返回 http.ErrNoCookie —— 这个错误常被静默吞掉,导致后续布尔判断永远走默认分支。


















