英文:
Why am I getting an "index out of range" error when base64 encoding a byte array?
问题
将字节数组编码为Base64字节数组时,上述代码会产生运行时的"索引超出范围"错误。如何解决这个问题?
package main
import (
"fmt"
"encoding/base64"
)
func main() {
data := []byte("string of data")
encodedData := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
base64.StdEncoding.Encode(encodedData, data)
fmt.Println(encodedData)
}
英文:
When encoding a byte array into a base64 byte array, the below code produces a runtime index out of range
error. How can this be resolved?
package main
import (
"fmt"
"encoding/base64"
)
func main() {
data := []byte("string of data")
var encodedData []byte
base64.StdEncoding.Encode(encodedData, data)
fmt.Println(encodedData)
}
答案1
得分: 11
错误信息是:
panic: 运行时错误:索引超出范围
goroutine 1 [运行中]:
encoding/base64.(*Encoding).Encode(0xc420056000, 0x0, 0x0, 0x0, 0xc42003bf30, 0xe, 0x20)
/usr/lib/go/src/encoding/base64/base64.go:113 +0x27b
main.main()
/home/martin/a.go:11 +0x9b
退出状态 2
shell 返回 1
如果我们查看 /usr/lib/go/src/encoding/base64/base64.go
的第113行,我们可以看到(缩写):
n := (len(src) / 3) * 3
for si < n {
// [..]
dst[di+0] = enc.encode[val>>18&0x3F]
dst[di+0] = enc.encode[val>>18&0x3F]
dst[di+1] = enc.encode[val>>12&0x3F]
// [..]
}
换句话说,这个函数直接设置了 dst
的索引。var encodedData []byte
的长度为零,所以你会得到 索引超出范围
的错误。
修复的一种方法是将该行改为:
encodedData := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
这将创建一个大小为第二个参数的数组。Base64 编码的数据比输入数据更大,因此需要使用 base64.StdEncoding.EncodedLen()
。
然而,这并不是最好的修复方法。文档 中提到:
> 对于大型数据流的单个块,不适合使用 Encode。应该使用 NewEncoder()。
将代码重写为使用 NewEncoder()
如下所示:
func main() {
data := []byte("string of data")
encodedData := &bytes.Buffer{}
encoder := base64.NewEncoder(base64.StdEncoding, encodedData)
defer encoder.Close()
encoder.Write(data)
fmt.Println(encodedData)
}
还有一些其他有用的函数,比如 EncodeToString()
,可以使上述代码更短、更方便:encodedData := base64.StdEncoding.EncodeToString(data)
。
英文:
The error is:
panic: runtime error: index out of range
goroutine 1 [running]:
encoding/base64.(*Encoding).Encode(0xc420056000, 0x0, 0x0, 0x0, 0xc42003bf30, 0xe, 0x20)
/usr/lib/go/src/encoding/base64/base64.go:113 +0x27b
main.main()
/home/martin/a.go:11 +0x9b
exit status 2
shell returned 1
If we look at /usr/lib/go/src/encoding/base64/base64.go
line 113, we see (abbreviated):
n := (len(src) / 3) * 3
for si < n {
// [..]
dst[di+0] = enc.encode[val>>18&0x3F]
dst[di+0] = enc.encode[val>>18&0x3F]
dst[di+1] = enc.encode[val>>12&0x3F]
// [..]
}
In other words, this function directly sets the index of dst
. The length of var encodedData []byte
is zero, so you get the index out of range
error.
One way to fix it would be to change the line to:
encodedData := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
Which will make an array of the size in the second argument. Base64 encoded data is larger than the input, hence the base64.StdEncoding.EncodedLen()
.
However, this is hardly the best way to fix it. The documentation mentions:
> Encode is not appropriate for use on individual blocks of a large data stream. Use NewEncoder() instead.
Rewriting the code to NewEncoder()
looks like:
func main() {
data := []byte("string of data")
encodedData := &bytes.Buffer{}
encoder := base64.NewEncoder(base64.StdEncoding, encodedData)
defer encoder.Close()
encoder.Write(data)
fmt.Println(encodedData)
}
There also some other useful functions, such as EncodeToString()
which make the above a bit shorter and more convenient: encodedData := base64.StdEncoding.EncodeToString(data)
.
答案2
得分: 4
为输出分配空间。例如,
package main
import (
"encoding/base64"
"fmt"
)
func main() {
data := []byte("string of data")
encodedData := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
base64.StdEncoding.Encode(encodedData, data)
fmt.Println(encodedData)
}
输出:
[99 51 82 121 97 87 53 110 73 71 57 109 73 71 82 104 100 71 69 61]
var encodedData []byte
是零字节。因此,index out of range
。
英文:
Allocate space for the output. For example,
package main
import (
"encoding/base64"
"fmt"
)
func main() {
data := []byte("string of data")
encodedData := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
base64.StdEncoding.Encode(encodedData, data)
fmt.Println(encodedData)
}
Output:
[99 51 82 121 97 87 53 110 73 71 57 109 73 71 82 104 100 71 69 61]
var encodedData []byte
is zero bytes. Therefore, index out of range
答案3
得分: 1
因为Encode函数期望dst
切片已经分配了正确的长度。
Encode函数使用指定的编码方式对src进行编码,将编码后的结果写入长度为EncodedLen(len(src))的dst切片中。
英文:
Because Encode expects the dst
slice to be allocated to the correct length.
> Encode encodes src using the encoding enc, writing
> EncodedLen(len(src)) bytes to dst.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论