处理Go语言中base64解码的错误

3
考虑以下简单的base64解码代码片段:
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))
}

这会按预期生成hello。 现在,如果我有意传入损坏的输入,例如。

const encoded string = "XXXXXaGVsbG8="

然后我按下了紧急线路,它给了我:
panic: illegal base64 data at input byte 11

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

看起来根据源代码这个问题,除了匹配字符串文字并向调用者返回更有意义的错误消息外,似乎没有太多可做的了:

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

除了字符串匹配,还必须有更优雅的方法来实现这一点。如何用类似于Go的方式来实现呢?

2个回答

6

请查看错误类型。例如,

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))
}

输出:

panic: 
base64 input is corrupt, check service Key

啊,没错,在Go语言中错误也有类型。我想最好先阅读手册,之后再提问。谢谢! - evilSnobu

1

看看这个实现(未导出的 base64.Encoding.decode() 方法),如果该方法返回错误,那么它只能是具体类型 base64.CorruptInputError。这种错误类型总是产生以下错误字符串:

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

除了一些极端情况(例如内存不足错误、修改执行代码等),如果base64.StdEncoding.DecodeString()返回一个错误,那么它的错误字符串始终包含字符串"illegal base64 data at input byte "(在当前版本中)。

没有必要检查其错误字符串,您可以将任何非nil返回的错误视为输入无效。而且错误字符串是一个实现细节,因此您也不应该依赖它。错误字符串是为人类而设计的,而不是为代码设计的。这就是encoding/base64包的实现方式,除此之外你不能进行更精细的错误处理(通常在Encoding.DecodeString()的情况下,也没有必要区分单独的错误情况)。

当一个包为不同的错误情况提供不同的错误值时,有技巧可以很好地处理它们。详情请查看这个问题:

Go是否有标准Err变量?

正如提到的,在encoding/base64包的情况下,会返回具体类型为base64.CorruptInputError的值,您可以使用type assertion来检查。请参见peterSO的答案。

1
你正在依赖于特定的实现和特定的时间点。不要这样做。 - peterSO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接