Why am I getting an "index out of range" error when base64 encoding a byte array?

arrays, base64, go

Solution

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)`.

Problem

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) } ``` Playground here

Original source