Go Base64 标准编码和 RawStdEncoding 有什么区别
Go 的 base64.StdEncoding 和 base64.RawStdEncoding 使用同一套标准 Base64 字母表,真正的区别是末尾是否保留 = 填充。需要和已有协议、签名格式或其他语言实现互通时,先确认对方是否允许填充,再让编码端和解码端成对选择;不要把 Raw 误解成 URL 安全编码。
StdEncoding使用标准填充字符=,输出长度通常是 4 的倍数。RawStdEncoding只取消填充,字母表仍是标准字母表,+和/的语义没有变化。- 协议两端必须共享同一个约定;字段只允许无填充时选 Raw,兼容 RFC 4648 标准形式时优先选 Std。
先看清两种编码真正差在哪里
把同一段字节交给两个编码器,最容易看出区别。下面的例子选择长度不是 3 的倍数的输入,这样标准编码会出现填充,而 Raw 变体会省略它:
package main
import (
"encoding/base64"
"fmt"
)
func main() {
input := []byte("Go")
// 两个编码器使用同一套标准 Base64 字母表,只比较填充策略。
standard := base64.StdEncoding.EncodeToString(input)
raw := base64.RawStdEncoding.EncodeToString(input)
fmt.Println(standard) // R28=
fmt.Println(raw) // R28
}

StdEncoding 的输出是 R28=,最后的等号用于把编码结果补齐到完整的 4 字符分组;RawStdEncoding 输出 R28,只省略这个填充字符。输入长度恰好是 3 的倍数时,两者可能看起来完全一样,所以不要用单个“无等号”的样例判断编码器。
标准字母表和 Raw 变体不要混为一谈
Base64 里有两个经常被同时讨论、但职责不同的选择:一是使用哪套 64 字符字母表,二是是否使用填充。StdEncoding 与 RawStdEncoding 都属于标准字母表;后者可以理解为标准编码的 NoPadding 版本。
| 编码器 | 字母表 | 填充 | 常见约束 |
|---|---|---|---|
StdEncoding | 标准 Base64 | 保留 = | 对接明确要求标准填充的协议或已有实现 |
RawStdEncoding | 标准 Base64 | 不保留 | 字段约定无填充,或长度希望更短 |
URLEncoding | URL 安全字母表 | 保留 = | 需要 URL 查询参数或路径安全字符时 |
RawURLEncoding | URL 安全字母表 | 不保留 | URL 安全且无填充的字段 |
本文只讨论前两行。若问题是“Base64 放进 URL 后出现 +、/ 或转义问题”,应另看 URL 安全字母表,不要只把 StdEncoding 换成 RawStdEncoding。
按协议约束选择编码器
选择时先问三个问题:对方是否明确要求 =;字段是否有固定长度或长度预算;对接方能否使用同样的解码器。只要协议文档给出一种形式,就以协议为准,不要因为 Raw 输出更短就自行切换。
package main
import (
"encoding/base64"
"fmt"
)
func encodeToken(raw []byte, withoutPadding bool) string {
// 无填充只能在协议允许时启用,否则会改变线上字段格式。
enc := base64.StdEncoding
if withoutPadding {
enc = base64.RawStdEncoding
}
return enc.EncodeToString(raw)
}
func main() {
token := []byte("user-42")
fmt.Println(encodeToken(token, false)) // 标准形式,可能带 '='
fmt.Println(encodeToken(token, true)) // Raw 形式,不带 '='
}
对于签名输入、缓存键和短令牌,编码结果本身常常会参与哈希或拼接。此时多一个 = 不只是显示差异,而是会改变待签名字符串;编码策略必须在协议层固定,并在文档中写清“标准填充”还是“无填充”。
编码端和解码端必须成对选择
编码端使用哪种形式,解码端就应该使用对应的 Encoding。不要先用字符串裁剪去掉等号,再交给标准解码器;也不要把收到的无填充字段无条件补等号,因为你可能会掩盖协议双方配置不一致的问题。
package main
import (
"encoding/base64"
"fmt"
)
func decodeToken(value string, withoutPadding bool) ([]byte, error) {
// 解码器与编码器保持同一填充约定,错误交给调用方处理。
enc := base64.StdEncoding
if withoutPadding {
enc = base64.RawStdEncoding
}
decoded, err := enc.DecodeString(value)
if err != nil {
return nil, fmt.Errorf("base64 解码失败: %w", err)
}
return decoded, nil
}

如果服务端返回带 = 的值,而客户端固定用 RawStdEncoding 解码,或者反过来,通常会得到格式错误。排查时先把原始传输值完整记录为安全的可复现样本,再确认两端的编码器名称、是否做过字符串裁剪,以及协议是否允许两种形式同时存在。
什么时候选 Std,什么时候选 Raw
可以把选择规则收敛成一张小表:
| 场景 | 推荐 | 原因 |
|---|---|---|
| 新协议没有特别限制 | StdEncoding | 标准形式更容易和默认实现互通 |
| 协议明确规定无填充 | RawStdEncoding | 直接表达无填充约定,避免手工裁剪 |
| 对接方只给出一个固定解码器 | 跟随对方 | 兼容性优先于本地输出长度 |
| 问题涉及 URL 字符 | 另选 URL 变体 | 填充策略和字母表是两个独立维度 |
最稳妥的工程做法是把编码器作为协议适配层的一部分,不在业务代码中到处直接调用全局变量;同时为带填充和无填充各保留一个明确的测试样例,覆盖输入长度不是 3 的倍数的情况。
常见问题
RawStdEncoding 会把 + 和 / 换掉吗?
不会。它只取消标准 Base64 的末尾填充,仍然使用标准字母表。如果还需要 URL 安全字符,应考虑 RawURLEncoding。
为什么我的测试里两个编码结果一样?
当输入字节数恰好是 3 的倍数时,标准编码不需要补 =,两者自然相同。测试时可以加入长度为 1、2、4 或 5 的输入。
能不能把等号删掉再用 StdEncoding 解码?
不建议。应该按协议直接使用对应的 Raw 解码器;手工删改会让格式约定散落在调用方,也可能使另一端无法判断真实编码形式。
Go base64.Strict 怎么拒绝非零填充位的编码输入
- 上一篇
- Go base64.Strict 怎么拒绝非零填充位的编码输入
- 下一篇
- Go base64.Decode 返回 n 和错误时怎么处理已写入字节
-
- Golang · Go问答 | 29分钟前 |
- Go cipher.AEAD.Open 认证失败时怎样安全处理输出缓冲区
- 137浏览 收藏
-
- Golang · Go问答 | 29分钟前 |
- Go base64.NewDecoder 读完数据后怎样发现尾部非法字符
- 354浏览 收藏
-
- Golang · Go问答 | 36分钟前 | base64 Go encoding/base64 RawURLEncoding URL安全编码
- Go Base64 URL 编码怎么去掉填充符又能正确解码
- 325浏览 收藏
-
- Golang · Go问答 | 38分钟前 |
- Go compress/zlib.NewReaderDict 遇到字典不匹配时怎么定位原因
- 432浏览 收藏
-
- Golang · Go问答 | 43分钟前 |
- Go ascii85.Decode 遇到不完整尾块时怎样判断输入是否截断
- 392浏览 收藏
-
- Golang · Go问答 | 43分钟前 |
- Go AST 删除节点后怎么用 CommentMap 保留注释归属
- 445浏览 收藏
-
- Golang · Go问答 | 48分钟前 |
- Go asn1.MarshalWithParams 怎么给顶层值添加显式标签
- 324浏览 收藏
-
- Golang · Go问答 | 50分钟前 | go · Go ASN.1 encoding/asn1 RawValue
- Go asn1.RawValue 怎么保留未知 ASN.1 字段的原始字节
- 257浏览 收藏
-
- Golang · Go问答 | 54分钟前 |
- Go encoding/asn1.Unmarshal 返回 rest 怎么判断还有多余 DER 数据
- 201浏览 收藏
-
- Golang · Go问答 | 56分钟前 | 标准库 · Go问答 · Go ASN.1 encoding/asn1 BitString RightAlign BIT STRING
- Go encoding/asn1.BitString.RightAlign 怎样恢复非字节对齐位串
- 342浏览 收藏
-
- Golang · Go问答 | 6小时前 | Go 注释 ast.NewCommentMap ParseComments
- Go ast.NewCommentMap 结果为空为什么要先检查解析模式
- 244浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 972次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 980次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 1093次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 1064次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 903次使用
-
- Go map 并发写 panic 怎么办:从共享 map 到可控写入路径
- 2026-06-30 123浏览
-
- Go Java 算法之字符串解码示例详解
- 2023-01-07 479浏览
-
- go语言中的defer关键字
- 2023-02-17 150浏览
-
- Golang中Interface接口的三个特性
- 2023-01-07 394浏览
-
- go语言中函数与方法介绍
- 2023-01-07 297浏览

