golang - base64简单解读

前端同学对base64的认识,往往是 图片可以用base64的方式来显示.

其实我们前后端最常用的jwt验证也是base64这种编码的.

今天就单独说base64编码本身.

声明

base64编码我们要看的是他的过程和标准.下面举例代码非js,但基本思路都是一样的,因为标准就一个.

上代码


const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

// The encoding pads the output to a multiple of 4 bytes,
// so Encode is not appropriate for use on individual blocks
// of a large data stream. Use NewEncoder() instead.
func (enc *Encoding) Encode(dst, src []byte) {
if len(src) == 0 {
return
}

di, si := 0, 0
// 能被3整除的最大的数
// 标准中说明3个字节要被转换为 4个 6bits的组
// a 24-bit input group is formed by concatenating 3 8-bit input groups.
n := (len(src) / 3) * 3
// n个组,每组是3个字节
for si < n {
// Convert 3x 8bit source bytes into 4 bytes
// 第一个8bits后面+16个0
// 第二个8bits后面+8个0
// 第三个8bits
// val -> [第一个8bits][第二个8bits][第三个8bits] 连接在一起 24bits
val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
// 取出最左6bits给 dst[0]
// 7-12 中间6bits给dst[1]
// 依次放入dst 共4组,每组6bits
dst[di+0] = enc.encode[val>>18&0x3F]
dst[di+1] = enc.encode[val>>12&0x3F]
dst[di+2] = enc.encode[val>>6&0x3F]
dst[di+3] = enc.encode[val&0x3F]

si += 3
di += 4
}
// 不能被整除剩余的字节
// 有的字可能2个或者1个字节就能表示了
// (1) The final quantum of encoding input is an integral multiple of 24
// bits; here, the final unit of encoded output will be an integral
// multiple of 4 characters with no "=" padding.
remain := len(src) - si
if remain == 0 {
return
}
// Add the remaining small block
// 拿到字符对应的ascii码,并左移16位 相当于 * 2^16
// val是多出的第一个字节
val := uint(src[si+0]) << 16
// 如果多出2个字节的情况 val 就是 [多出的第一个8bits][多出的第二个8bits][8个0] 共24bits连接
if remain == 2 {
val |= uint(src[si+1]) << 8
}
// 取最左6bits
// 6位都是1也就是63,在64内,拿到对应的字符进入dst
dst[di+0] = enc.encode[val>>18&0x3F]
// 取中间6bits
dst[di+1] = enc.encode[val>>12&0x3F]

switch remain {
case 2:
// (3) The final quantum of encoding input is exactly 16 bits; here, the
// final unit of encoded output will be three characters followed by
// one "=" padding character.
// 取第三个6bits出来
dst[di+2] = enc.encode[val>>6&0x3F]
if enc.padChar != NoPadding {
// 根据标准要+一个pad
dst[di+3] = byte(enc.padChar)
}
case 1:
// (2) The final quantum of encoding input is exactly 8 bits; here, the
// final unit of encoded output will be two characters followed by
// two "=" padding characters.
if enc.padChar != NoPadding {
// 根据标准+2个pad
dst[di+2] = byte(enc.padChar)
dst[di+3] = byte(enc.padChar)
}
}
}

上面代码只是针对标准的encode做出了说明.

对于URLencode 会有些不同

主要区别是

const encodeURL = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_”
请对比上面的标准字符集
const encodeStd = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/“
想看具体标准内容的,请走传送门 https://tools.ietf.org/html/rfc4648