encoding/base64 implements the base64 encoding from RFC 4648, turning arbitrary bytes into a compact, printable alphabet and back. Four ready-made Encoding values cover the standard, URL-safe, and unpadded variants.
EncodeToString and DecodeString on base64.StdEncoding are the two functions most code needs: bytes in, base64 text out, and back again.
msg := "Hello, 世界"
encoded := base64.StdEncoding.EncodeToString([]byte(msg))
fmt.Println(encoded)
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(decoded))Every 3 raw bytes become 4 base64 characters, and the result is padded with = up to a multiple of 4 unless padding is explicitly turned off.
$ go run main.go
SGVsbG8sIOS4lueVjA==
Hello, 世界Try it
Examples
EncodedLen tells you how big the output buffer needs to be before a one-shot Encode call; EncodeToString skips that step for the common case.
data := []byte("go gopher")
fmt.Println(base64.StdEncoding.EncodedLen(len(data)))
fmt.Println(base64.StdEncoding.EncodeToString(data))12
Z28gZ29waGVyStdEncoding's + and / aren't safe to drop into a URL path unescaped; URLEncoding swaps them for - and _.
data := []byte{0xfb, 0xff, 0xbf}
fmt.Println(base64.StdEncoding.EncodeToString(data))
fmt.Println(base64.URLEncoding.EncodeToString(data))+/+/
-_-_RawStdEncoding is StdEncoding with padding turned off, useful whenever the trailing = characters aren't wanted.
data := []byte("hi")
fmt.Println(base64.StdEncoding.EncodeToString(data))
fmt.Println(base64.RawStdEncoding.EncodeToString(data))aGk=
aGkNewEncoder wraps any io.Writer; Close flushes the last partial 4-byte block, so skipping it silently truncates the output.
var buf bytes.Buffer
enc := base64.NewEncoder(base64.StdEncoding, &buf)
enc.Write([]byte("foo\x00bar"))
enc.Close()
fmt.Println(buf.String())Zm9vAGJhcg==NewEncoding accepts any 64-byte alphabet, so a reversed or shuffled character set produces a different, still-valid encoding of the same bytes.
reversed := "/+9876543210zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA"
custom := base64.NewEncoding(reversed)
fmt.Println(base64.StdEncoding.EncodeToString([]byte("hi!")))
fmt.Println(custom.EncodeToString([]byte("hi!")))aGkh
l5beConstants and package encodings
| Function | Description |
|---|---|
const StdPadding rune = '=' | The default padding character used by StdEncoding and URLEncoding. |
const NoPadding rune = -1 | Passed to WithPadding to disable padding entirely. |
var StdEncoding *Encoding base64.StdEncoding.EncodeToString([]byte("hi")) // "aGk=" | The standard base64 alphabet from RFC 4648, using + and /. |
var URLEncoding *Encoding | The alternate RFC 4648 alphabet with - and _ in place of + and /, safe to drop directly into a URL or filename. |
var RawStdEncoding *Encoding | StdEncoding with padding disabled: StdEncoding.WithPadding(NoPadding). |
var RawURLEncoding *Encoding | URLEncoding with padding disabled: URLEncoding.WithPadding(NoPadding). |
Building a custom Encoding
| Function | Description |
|---|---|
NewEncoding(encoder string) *Encoding | Builds a custom Encoding from a 64-byte alphabet string; the alphabet can't contain '=', '\r', or '\n', and must have no repeated bytes. |
(Encoding) WithPadding(padding rune) *Encoding | Returns a copy of enc using a different padding character, or NoPadding to disable padding. |
(Encoding) Strict() *Encoding | Returns a copy of enc that rejects input whose unused padding bits aren't zero, per RFC 4648 section 3.5. |
Encoding
| Function | Description |
|---|---|
(*Encoding) EncodeToString(src []byte) string base64.StdEncoding.EncodeToString([]byte("any + old & data")) | Returns the base64 encoding of src as a string, the usual entry point for encoding. |
(*Encoding) Encode(dst, src []byte) | Writes EncodedLen(len(src)) bytes to dst, a caller-allocated buffer. Not meant for streaming individual blocks of a larger source; use NewEncoder for that. |
(*Encoding) AppendEncode(dst, src []byte) []byte | Appends the encoding of src to dst and returns the grown slice, avoiding a separate allocation for the result. |
(*Encoding) EncodedLen(n int) int | Returns how many bytes n bytes of input encode to, for sizing a destination buffer before calling Encode. |
Decoding
| Function | Description |
|---|---|
(*Encoding) DecodeString(s string) ([]byte, error) base64.StdEncoding.DecodeString("aGk=") // []byte("hi"), nil | Decodes a base64 string back to bytes, the usual entry point for decoding. |
(*Encoding) Decode(dst, src []byte) (n int, err error) | Writes at most DecodedLen(len(src)) bytes to dst and returns how many were written; on malformed input it returns a CorruptInputError plus whatever decoded successfully. |
(*Encoding) AppendDecode(dst, src []byte) ([]byte, error) | Appends the decoding of src to dst and returns the grown slice. |
(*Encoding) DecodedLen(n int) int | Returns the maximum number of bytes n bytes of base64 could decode to, for sizing a destination buffer before calling Decode. |
Streaming
| Function | Description |
|---|---|
NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser | Wraps w so writes are base64-encoded before landing on the underlying writer; encoding happens in 4-byte blocks, so Close must be called to flush the final partial block. |
NewDecoder(enc *Encoding, r io.Reader) io.Reader | Wraps r so reads come back base64-decoded; needs no Close since decoding never buffers a trailing partial block. |
Errors
| Function | Description |
|---|---|
type CorruptInputError int64 | Returned by Decode, DecodeString, and AppendDecode when the input isn't valid base64 for the encoding in use; the value is the byte offset of the bad input. |
(CorruptInputError) Error() string | Formats the error with the offending byte offset. |
Choosing an encoding
All four package-level encodings share the same underlying alphabet split between the standard and URL-safe variants; padding is the other independent choice, since either alphabet can be built with or without it.
// Four ready-made Encodings cover the common combinations:
base64.StdEncoding // + / padded - general purpose, MIME/PEM
base64.URLEncoding // - _ padded - safe inside a URL path or filename
base64.RawStdEncoding // + / unpadded - same alphabet, no trailing =
base64.RawURLEncoding // - _ unpadded - most common choice for tokens and IDsA CorruptInputError is just an int64 byte offset under the hood, so unwrapping it with errors.As hands back exactly where decoding gave up.
// Decode reports a CorruptInputError instead of panicking on bad input.
_, err := base64.StdEncoding.DecodeString("not@valid!!")
var corruptErr base64.CorruptInputError
if errors.As(err, &corruptErr) {
fmt.Println("bad byte at offset", int64(corruptErr))
}The offset points at the first character outside the base64 alphabet, here the @ four characters in.
$ go run main.go
bad byte at offset 3