【问题标题】:Why am I getting an "index out of range" error when base64 encoding a byte array?为什么在 base64 编码字节数组时出现“索引超出范围”错误?
【发布时间】:2017-10-01 23:12:53
【问题描述】:

将字节数组编码为 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

【问题讨论】:

    标签: arrays go base64


    【解决方案1】:

    错误是:

    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)

    【讨论】:

    • 感谢您的深入回答!编码后的数据将如何被解码?
    • 我相信你能找到这个问题的答案in the documentation@jscionti :-)
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      为输出分配空间。例如,

      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-08-22
        • 2015-09-12
        • 2017-12-02
        • 2020-09-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多