Base64编码/解码导致输出损坏。

huangapple go评论85阅读模式
英文:

Base64 encode/decode results in corrupted output

问题

我正在尝试编写一些方便的包装函数,用于对字节切片进行base64编码和解码。(不明白为什么标准库没有提供方便的方法。)

然而,当我尝试打印输出时,这段代码(在playground中)会生成截断的输出:

func b64encode(b []byte) []byte {
    encodedData := &bytes.Buffer{}
    encoder := base64.NewEncoder(base64.URLEncoding, encodedData)
    defer encoder.Close()
    encoder.Write(b)
    return encodedData.Bytes()
}

func b64decode(b []byte) ([]byte, error) {
    dec := base64.NewDecoder(base64.URLEncoding, bytes.NewReader(b))
    buf := &bytes.Buffer{}
    _, err := io.Copy(buf, dec)
    if err != nil {
        return nil, err
    }
    return buf.Bytes(), nil
}


func main() {
    b := []byte("hello")
    e := b64encode(b)
    d, err := b64decode(e)
    if err != nil {
        log.Fatalf("could not decode: %s", err)
    }
    fmt.Println(string(d))
}

发生了什么情况?

英文:

I'm trying to write some convenience wrapper funcs that base64 encodes and decodes byte slices. (Can't understand why this is not conveniently provided in the stdlib.)

However this code (in playground):

func b64encode(b []byte) []byte {
	encodedData := &bytes.Buffer{}
	encoder := base64.NewEncoder(base64.URLEncoding, encodedData)
	defer encoder.Close()
	encoder.Write(b)
	return encodedData.Bytes()
}

func b64decode(b []byte) ([]byte, error) {
	dec := base64.NewDecoder(base64.URLEncoding, bytes.NewReader(b))
	buf := &bytes.Buffer{}
	_, err := io.Copy(buf, dec)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}


func main() {
	b := []byte("hello")
	e := b64encode(b)
	d, err := b64decode(e)
	if err != nil {
		log.Fatalf("could not decode: %s", err)
	}
	fmt.Println(string(d))
}

generates truncated output when I try to print it:

hel

What's going on?

答案1

得分: 8

defer语句在函数结束时执行,也就是在return语句被评估之后执行。

以下是一个可行的示例:https://play.golang.org/p/sYn-W6fZh1

func b64encode(b []byte) []byte {
    encodedData := &bytes.Buffer{}
    encoder := base64.NewEncoder(base64.URLEncoding, encodedData)
    encoder.Write(b)
    encoder.Close()
    return encodedData.Bytes()
}

然而,如果所有操作都在内存中进行,你可以完全避免创建编码器。可以使用以下方式:

func b64encode(b []byte) []byte {
    ret := make([]byte, base64.URLEncoding.EncodedLen(len(b)))
    base64.URLEncoding.Encode(ret, b)
    return ret
}

这种方式的额外好处是更高效,因为它只需要分配一次内存。同时,它还允许你不再忽略WriteClose方法中的错误。

英文:

The defer executes when the function ends. That is AFTER the return statement has been evaluated.

The following works: https://play.golang.org/p/sYn-W6fZh1

func b64encode(b []byte) []byte {
	encodedData := &bytes.Buffer{}
	encoder := base64.NewEncoder(base64.URLEncoding, encodedData)
	encoder.Write(b)
	encoder.Close()
	return encodedData.Bytes()
}

That being said, if it really is all in memory, you can avoid creating an encoder entirely. Instead, you can do something like:

func b64encode(b []byte) []byte {
    ret := make([]byte, base64.URLEncoding.EncodedLen(len(b)))
    base64.URLEncoding.Encode(ret, b)
    return ret
}

An added benefit of doing it this way it it is more efficient since it only needs to allocate once. It also allows you to no longer ignore errors in the Write and Close methods.

huangapple
  • 本文由 发表于 2017年8月30日 04:59:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/45948230.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定