英文:
Why does Go use bit operation in base64 encode?
问题
代码2是Go语言的base64编码的base64.Encode函数。
这段代码多次使用了位运算。
例如,
val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
还有,
val := uint(src[si+0])>>18&0x3F]
我不知道为什么需要这些位运算来进行base64编码。
这些位运算的含义是什么?
代码:
func (enc *Encoding) Encode(dst, src []byte) {
if len(src) == 0 {
return
}
di, si := 0, 0
n := (len(src) / 3) * 3
for si < n {
// Convert 3x 8bit source bytes into 4 bytes
val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
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
}
remain := len(src) - si
if remain == 0 {
return
}
// Add the remaining small block
val := uint(src[si+0]) << 16
if remain == 2 {
val |= uint(src[si+1]) << 8
}
dst[di+0] = enc.encode[val>>18&0x3F]
dst[di+1] = enc.encode[val>>12&0x3F]
switch remain {
case 2:
dst[di+2] = enc.encode[val>>6&0x3F]
if enc.padChar != NoPadding {
dst[di+3] = byte(enc.padChar)
}
case 1:
if enc.padChar != NoPadding {
dst[di+2] = byte(enc.padChar)
dst[di+3] = byte(enc.padChar)
}
}
}
英文:
Code 2 is base64.Encode of Go.
This code uses bit operation many times.
For example,
val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
And,
val := uint(src[si+0])>>18&0x3F]
I don't know why these bit operations are need to encode to base64.
What is the meaning of these bit operations?
Code:
func (enc *Encoding) Encode(dst, src []byte) {
if len(src) == 0 {
return
}
di, si := 0, 0
n := (len(src) / 3) * 3
for si < n {
// Convert 3x 8bit source bytes into 4 bytes
val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
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
}
remain := len(src) - si
if remain == 0 {
return
}
// Add the remaining small block
val := uint(src[si+0]) << 16
if remain == 2 {
val |= uint(src[si+1]) << 8
}
dst[di+0] = enc.encode[val>>18&0x3F]
dst[di+1] = enc.encode[val>>12&0x3F]
switch remain {
case 2:
dst[di+2] = enc.encode[val>>6&0x3F]
if enc.padChar != NoPadding {
dst[di+3] = byte(enc.padChar)
}
case 1:
if enc.padChar != NoPadding {
dst[di+2] = byte(enc.padChar)
dst[di+3] = byte(enc.padChar)
}
}
}
答案1
得分: 1
这是同样算法的JavaScript实现的注释版本:https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64#Javascript
它告诉你这个循环:
-
获取三个ASCII字符(8位):
src[si+0]
,src[si+1]
和src[si+2]
-
将它们合并为一个24位的数字(即
val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
) -
将这个数字重新分成四个索引(6位),用于base64字符列表。(
val>>18&0x3F
获取先前计算的数字的第18到24位,依此类推)
你也可以阅读这个:https://en.wikipedia.org/wiki/Base64#Examples
英文:
Here is a commented Javascript implementation of the same algorithm: https://en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64#Javascript
It tells you that this loop:
-
takes three ASCII chars (8-bit):
src[si+0]
,src[si+1]
andsrc[si+2]
-
merges them into one 24-bit number (that's
val := uint(src[si+0])<<16 | uint(src[si+1])<<8 | uint(src[si+2])
) -
re-separate this number into four indices (6-bit) for the base64 character list. (
val>>18&0x3F
takes the 18th to 24th bit of the previously calculated number, etc.)
You can also read this: https://en.wikipedia.org/wiki/Base64#Examples
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论