在 Go 中处理来自 base64 解码的错误
Handling errors from base64 decode in Go
考虑这个简单的 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
查看 source code and this issue,除了匹配字符串文字并向调用者返回更有意义的错误消息外,这里似乎没什么可做的:
if err != nil {
if strings.Contains(err.Error(), "illegal base64 data at input byte") {
panic("\nbase64 input is corrupt, check service Key")
}
}
除了字符串匹配之外,必须有更优雅的方法来做到这一点。
go-esque 方法是什么?
查看实现(未导出的base64.Encoding.decode()
方法),如果该方法returns出错,它只能是具体类型base64.CorruptInputError
。此错误类型总是产生以下错误字符串:
func (e CorruptInputError) Error() string {
return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
}
所以除了一些极端情况(如内存不足错误,修改执行代码等)如果 base64.StdEncoding.DecodeString()
returns 一个错误,它的错误字符串将 always 包含字符串 "illegal base64 data at input byte "
(在当前版本中)。
无需检查其错误字符串,您可以将任何非nil
返回的错误视为输入无效。错误字符串是一个实现细节,所以无论如何你都不应该依赖它。错误字符串适用于 humans,不适用于 code。这就是 encoding/base64
包的实现方式,除此之外你不能做任何更精细的错误处理(通常在 Encoding.DecodeString()
的情况下不需要区分单独的错误情况)。
当一个包确实为不同的错误情况提供不同的错误值时,有一些技术可以很好地处理它们。有关详细信息,请查看此问题:
如前所述,在 encoding/base64
包的情况下,返回具体 base64.CorruptInputError
类型的值,您可以使用 type assertion 来检查它。请参阅 peterSO 的回答。
查看错误类型。例如,
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
考虑这个简单的 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
查看 source code and this issue,除了匹配字符串文字并向调用者返回更有意义的错误消息外,这里似乎没什么可做的:
if err != nil {
if strings.Contains(err.Error(), "illegal base64 data at input byte") {
panic("\nbase64 input is corrupt, check service Key")
}
}
除了字符串匹配之外,必须有更优雅的方法来做到这一点。 go-esque 方法是什么?
查看实现(未导出的base64.Encoding.decode()
方法),如果该方法returns出错,它只能是具体类型base64.CorruptInputError
。此错误类型总是产生以下错误字符串:
func (e CorruptInputError) Error() string {
return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
}
所以除了一些极端情况(如内存不足错误,修改执行代码等)如果 base64.StdEncoding.DecodeString()
returns 一个错误,它的错误字符串将 always 包含字符串 "illegal base64 data at input byte "
(在当前版本中)。
无需检查其错误字符串,您可以将任何非nil
返回的错误视为输入无效。错误字符串是一个实现细节,所以无论如何你都不应该依赖它。错误字符串适用于 humans,不适用于 code。这就是 encoding/base64
包的实现方式,除此之外你不能做任何更精细的错误处理(通常在 Encoding.DecodeString()
的情况下不需要区分单独的错误情况)。
当一个包确实为不同的错误情况提供不同的错误值时,有一些技术可以很好地处理它们。有关详细信息,请查看此问题:
如前所述,在 encoding/base64
包的情况下,返回具体 base64.CorruptInputError
类型的值,您可以使用 type assertion 来检查它。请参阅 peterSO 的回答。
查看错误类型。例如,
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