为什么我的"索引超出范围" base64编码字节数组时出错?

时间:2017-05-03 23:31:38

标签: arrays go base64

将字节数组编码为base64字节数组时,以下代码会产生运行时index out of range错误。怎么解决这个问题?

package main

import (
    "fmt"
    "encoding/base64"
)

func main() {
    data := []byte("string of data")
    var encodedData []byte
    base64.StdEncoding.Encode(encodedData, data)
    fmt.Println(encodedData)
}

Playground here

3 个答案:

答案 0 :(得分:7)

错误是:

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

如果我们查看/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的长度为零,因此您会收到index out of range错误。

修复它的一种方法是将行更改为:

encodedData := make([]byte, base64.StdEncoding.EncodedLen(len(data)))

这将在第二个参数中生成一个大小的数组。 Base64编码数据大于输入,因此base64.StdEncoding.EncodedLen()

但是,这不是修复它的最佳方法。 The documentation提及:

  

编码不适合在大型数据流的各个块上使用。请改用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)

答案 1 :(得分: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

答案 2 :(得分:1)

因为Encode期望将dst切片分配到正确的长度。

  

使用编码enc编写对src进行编码编码   EncodedLen(len(src))字节到dst。