天天看点

Go使用Base64编解码简介Encoding应用流式API的应用

简介

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,可用于在HTTP环境下传递较长的标识信息。Go 的 encoding/base64 提供了对base64的编解码操作。

encoding/base64 定义了一个Encoding结构体,表示Base64的编/解码器。并且导出了四个常用的Encoding对象:StdEncoding、URLEncoding、RawStdEncoding、RawURLEncoding。StdEncoding表示标准的编/解码器。URLEncoding用于对URL编解码,编解码过程中会将Base64编码中的特殊标记+和/替换为-和_。RawStdEncoding和RawURLEncoding是StdEncoding和URLEncoding的非padding版本。主要API如下:

// 四个导出的编码/解码器
var StdEncoding = NewEncoding(encodeStd)
var URLEncoding = NewEncoding(encodeURL)
var RawStdEncoding = StdEncoding.WithPadding(NoPadding)
var RawURLEncoding = URLEncoding.WithPadding(NoPadding)

// Encoding 结构体表示编码/解码器
type Encoding struct {
    // ...
}

// Encoding提供了如下编解码的方法
// 解码,[]byte版本将src解码为dest,返回成功写入的字节数和错误
// string版本应用于字符串
func (enc *Encoding) Decode(dst, src []byte) (n int, err error)
func (enc *Encoding) DecodeString(s string) ([]byte, error)
// 编码,[]byte版本将src编码为dest
// string版本应用于字符串
func (enc *Encoding) Encode(dst, src []byte)
func (enc *Encoding) EncodeToString(src []byte) string
// 设置enc的padding,返回Encoding指针,NoPadding表示不进行padding操作
func (enc Encoding) WithPadding(padding rune) *Encoding

// 另外 encoding/base64 还提供了流式操作的接口
func NewDecoder(enc *Encoding, r io.Reader) io.Reader
func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser
           

Encoding应用

下面的程序演示了 Encoding 的用法:

package main

import (
    "encoding/base64"
    "errors"
    "fmt"
)

// 为了方便,声明该函数,省去错误处理
func mustDecode(enc *base64.Encoding, str string) string {
    data, err := enc.DecodeString(str)
    if err != nil {
        panic(err)
    }
    return string(data)
}

// 该函数测试编解码
// enc为要测试的Encoding对象,str为要测试的字符串
func testEncoding(enc *base64.Encoding, str string) {
    // 编码
    encStr := enc.EncodeToString([]byte(str))
    fmt.Println(encStr)

    // 解码
    decStr := mustDecode(enc, encStr)
    if decStr != str {  // 编码后再解码应该与原始字符串相同
                        // 这里判断如果不同,则panic
        panic(errors.New("unequal!"))
    }
}

func main() {
    const testStr = "Go语言编程"

    // 测试StdEncoding,注意打印结果里的/为URL中的特殊字符,最后有一个padding
    testEncoding(base64.StdEncoding, testStr)    // 打印:R2/or63oqIDnvJbnqIs=

    // 测试URLEncoding,可以看到/被替换为_
    testEncoding(base64.URLEncoding, testStr)    // 打印:R2_or63oqIDnvJbnqIs=

    // 测试RawStdEncoding,可以看到去掉了padding
    testEncoding(base64.RawStdEncoding, testStr) // 打印:R2/or63oqIDnvJbnqIs

    // 测试RawURLEncoding,可以看到/被替换Wie_,并且却掉了padding
    testEncoding(base64.RawURLEncoding, testStr) // 打印:R2_or63oqIDnvJbnqIs
}
           

流式API的应用

流式API多用于在数据传输过程中对数据进行Base64编码或解码。比如在读取较大文件时,或者网络传输时。下面的程序读取testfile中的数据,利用base64编码后保存到testfile_enc:

package main

import (
    "encoding/base64"
    "io"
    "log"
    "os"
)

type Buf struct {
    data []byte
    size int
}

func main() {

    f, err := os.Open("E:\\testfile")
    if err != nil {
        log.Fatalln(err)
    }
    defer f.Close()

    fEnc, err := os.Create("E:\\testfile_enc")
    if err != nil {
        log.Fatalln(err)
    }
    defer fEnc.Close()

    w := base64.NewEncoder(base64.StdEncoding, fEnc)
    io.Copy(w, f)
    w.Close()
}