Error handling with base64 decoding in Go

Consider this simple base64 snippet:

package main

import (
    "fmt"
    "encoding/base64"
)

func main() {
    const encoded string = "aGVsbG8=" // hello
    decoded, err := base64.StdEncoding.DecodeString(encoded)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(decoded))
}

      

This gives hi as expected. Now if I am deliberately passing in corrupted input like

const encoded string = "XXXXXaGVsbG8="

      

then I find myself hitting the panic line which gives me:

panic: illegal base64 data at input byte 11

goroutine 1 [running]:
main.main()
    /tmp/sandbox422941756/main.go:12 +0x140

      

Looking at the source code and this issue , it seems like there isn't much here other than matching the string literal and returning a more meaningful message to the caller of the caller:

if err != nil {
    if strings.Contains(err.Error(), "illegal base64 data at input byte") {
        panic("\nbase64 input is corrupt, check service Key")
    }
}

      

There must be a more elegant way to do this besides string matching. What is the go- reactive way to achieve this?

+3


source to share


2 answers


Look at the type of error. For example,

package main

import (
    "encoding/base64"
    "fmt"
)

func main() {
    encoded := "XXXXXaGVsbG8=" // corrupt
    decoded, err := base64.StdEncoding.DecodeString(encoded)
    if err != nil {
        if _, ok := err.(base64.CorruptInputError); ok {
            panic("\nbase64 input is corrupt, check service Key")
        }
        panic(err)
    }
    fmt.Println(string(decoded))
}

      



Output:

panic: 
base64 input is corrupt, check service Key

      

+3


source


Looking at the implementation (non-ported base64.Encoding.decode()

method), if this method returns an error, it can only be a specific type base64.CorruptInputError

. This type of error always produces the following error line:

func (e CorruptInputError) Error() string {
    return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
}

      

Thus, apart from some extreme circumstances (for example, memory errors, changed execution code, etc.), if it base64.StdEncoding.DecodeString()

returns an error, the error string always contains a string "illegal base64 data at input byte "

(in the current version).

There is no need to validate your error string, you can handle any returned error not nil

as the input is invalid. And the error string is an implementation detail, so you shouldn't rely on it anyway. The error line is for people, not code. This is how the package is implemented encoding/base64

, you cannot do finer error handling alongside this (and there is usually no need to distinguish between individual error cases in a case Encoding.DecodeString()

).



When a packet gives different error values ​​for different error cases, there are methods to effectively manage them. For more information, check out this question:

Are there standard Err variables?

As mentioned, in the case of a package encoding/base64

, a type value is returned base64.CorruptInputError

, you can use type assertion to check this. See peterSO's answer for this.

+1


source







All Articles