如果对字符串"ab"进行Base64编码,得到的结果将是:YWI=,结果中为什么会出现=呢,这就需要了解一下base64编码背后的原理。
Base64是一种便于网络传输的字节码编码方式,之所以叫Base64是由于它的编码结果是由64个可打印字符组成,这些字符在不同系统间是通用的。
索引 |
对应字符 |
索引 |
对应字符 |
索引 |
对应字符 |
索引 |
对应字符 |
0 |
A |
17 |
R |
34 |
i |
51 |
z |
1 |
B |
18 |
S |
35 |
j |
52 |
0 |
2 |
C |
19 |
T |
36 |
k |
53 |
1 |
3 |
D |
20 |
U |
37 |
l |
54 |
2 |
4 |
E |
21 |
V |
38 |
m |
55 |
3 |
5 |
F |
22 |
W |
39 |
n |
56 |
4 |
6 |
G |
23 |
X |
40 |
o |
57 |
5 |
7 |
H |
24 |
Y |
41 |
p |
58 |
6 |
8 |
I |
25 |
Z |
42 |
q |
59 |
7 |
9 |
J |
26 |
a |
43 |
r |
60 |
8 |
10 |
K |
27 |
b |
44 |
s |
61 |
9 |
11 |
L |
28 |
c |
45 |
t |
62 |
+ |
12 |
M |
29 |
d |
46 |
u |
63 |
/ |
13 |
N |
30 |
e |
47 |
v |
||
14 |
O |
31 |
f |
48 |
w |
||
15 |
P |
32 |
g |
49 |
x |
||
16 |
Q |
33 |
h |
50 |
y |
大家可以看到这里面并没 '=' 这个字符,这是因为 ’=‘ 其实是填充字符。
如果需要表示上面的64个字符,那么需要6bit,也就是2^6=64,base64的核心思想就是,将3个
字节拆分成4个6bit,然后对每个6bit的高位补2个0,构成1个字节。也即是每3个字节最终结果将变成4个字节。
如果原始字符串的字节数不是3的整数倍,那么就用0来填充,用来填充的0就被编码成了'=',这就是出现=的原因,并且只会出现在结果出,如果原始字符刚好是3字节的整数倍,那么就没有等号了。
回到开头的例子,我们看下ab是如何计算得到YWI=的。
需要注意填充的0是要被转化成=,而不是上表中的A。
1 2 3 4 5 6 7 8 9 |
func main() { str := "ab" // base64编码 encodedStr := base64.URLEncoding.EncodeToString([]byte(str)) fmt.Println(encodedStr) // YWI= // base64解码 decodeStr, _ := base64.URLEncoding.DecodeString(encodedStr) fmt.Println(string(decodeStr)) // ab } |
如果不希望保留填充的=,可以在编码后去掉,解码前填充上
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
func main(){ str := "ab" // base64编码 encodedStr := base64.URLEncoding.EncodeToString([]byte(str)) encodedStr = strings.TrimRight(encodedStr, "=") // 去掉填充的= fmt.Println(encodedStr) // YWI // 解码时,长度不是4的倍数,需要用=填充 i := len(encodedStr) % 4 if i != 0 { encodedStr += strings.Repeat("=", 4-i) } // base64解码 decodeStr, _ := base64.URLEncoding.DecodeString(encodedStr) fmt.Println(string(decodeStr)) // ab |