天天看點

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