duanpin2009
2017-07-02 10:53
浏览 462
已采纳

在Go中处理来自base64解码的错误

Consider this simple base64 decode 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 produces hello as expected. Now, if i intentionally pass in corrupt input, e.g.

const encoded string = "XXXXXaGVsbG8="

then i hit 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, seems there is not much to go by here other than matching the string literal and returning a more meaningful error message to the caller:

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

There has to be a more elegant way to do this other than string matching. What is the go-esque way to achieve this?

图片转代码服务由CSDN问答提供 功能建议

考虑以下简单的base64解码代码段:

  package main \  n 
import(
“ fmt” 
“ encoding / base64” 
)
 
func main(){
 const编码的字符串=“ aGVsbG8 =” //您好
已解码,错误:= base64.StdEncoding  .DecodeString(已编码)
,如果出错!= nil {
 panic(err)
} 
 fmt.Println(string(decoded))
} 
   
 
  

这将按预期产生 hello 。 现在,如果我有意传入错误的输入,例如

  const编码的字符串=“ XXXXXaGVsbG8 =”  
   
 
 

然后我进入了恐慌行,这给了我:

 恐慌:输入字节11处的非法base64数据 
 
goroutine 1 [运行中]:
main.main()
 /tmp/sandbox422941756/main.go:12 + 0x140 
   
 
 

在< a href =“ https://github.com/golang/go/issues/10290” rel =“ nofollow noreferrer”>源代码和此问题,似乎 s除了匹配字符串文字并向调用者返回更有意义的错误消息外,这里没有其他事情要做:

  if err!= nil {
如果是字符串 .Contains(err.Error(),“输入字节处的非法base64数据”)){
 panic(“ 
base64输入已损坏,请检查服务密钥”)
} 
} 
   
 
 

除了字符串匹配之外,还必须有一种更优雅的方法。 什么是实现这种目标的 go 方式? < / DIV>

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • douweng7083 2017-07-02 11:20
    已采纳

    Look at the error type. 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("
    base64 input is corrupt, check service Key")
            }
            panic(err)
        }
        fmt.Println(string(decoded))
    }
    

    Output:

    panic: 
    base64 input is corrupt, check service Key
    
    已采纳该答案
    打赏 评论
  • dpr77335 2017-07-02 11:15

    Looking at the implementation (unexported base64.Encoding.decode() method), if that method returns an error, it can only be of concrete type base64.CorruptInputError. This error type always produces the following error string:

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

    So beside some extreme circumstances (like out of memory error, modified execution code etc.) if base64.StdEncoding.DecodeString() returns an error, its error string will always contain the string "illegal base64 data at input byte " (in the current version).

    It's needless to check its error string, you can treat any non-nil returned error as the input being invalid. And the error string is an implementation detail, so you shouldn't rely on it anyway. The error string is for humans, not for code. This is how the encoding/base64 package is implemented, you can't do any finer error handling beside this (and usually there is no need to distinguish separate error cases in case of Encoding.DecodeString()).

    When a package does give distinct error values for different error cases, there are techniques to handle them well. For details, check out this question:

    Does go have standard Err variables?

    As mentioned, in case of the encoding/base64 package a value of the concrete base64.CorruptInputError type is returned, you can use type assertion to check for that. See peterSO's answer for that.

    打赏 评论

相关推荐 更多相似问题