Декодирование Base64 в Go — Руководство encoding/base64

·Systems Engineer·ПровереноHana Nováková·Опубликовано

Используйте бесплатный Base64 Decode Online прямо в браузере — установка не требуется.

Попробовать Base64 Decode Online онлайн →

Декодирование Base64 в Go встречается постоянно — при инспекции JWT, работе с бинарными вложениями файлов, а также с API-payload облачных сервисов. Стандартный пакет Go encoding/base64справляется со всем этим, однако выбор неверного варианта кодировки (стандартная против URL-safe, с паддингом против без) — самая распространённая причина ошибок “illegal base64 data”. В этом руководстве рассматриваются StdEncoding, URLEncoding, RawURLEncoding, потоковое декодирование через base64.NewDecoder, инспекция JWT payload и четыре ошибки, на которые натыкаются почти все в первый раз. Для разового декодирования прямо в браузере Base64 Decoder от ToolDeck справится мгновенно — без единой строки кода.

  • encoding/base64 входит в стандартную библиотеку Go — никакого go get не требуется
  • Используйте RawURLEncoding для JWT-токенов и большинства современных API (без паддинга, URL-safe алфавит)
  • StdEncoding использует + и / с паддингом =; URLEncoding заменяет их на - и _, но паддинг сохраняет
  • base64.NewDecoder оборачивает любой io.Reader для потокового декодирования без загрузки в память
  • Всегда проверяйте возвращаемую ошибку — неверный паддинг и неправильный алфавит дают ошибку illegal base64 data

Что такое декодирование Base64?

Base64-кодирование представляет бинарные данные в виде ASCII-текста, используя 64 печатных символа (A–Z, a–z, 0–9 плюс два дополнительных). Декодирование выполняет обратную операцию — преобразует это ASCII-представление обратно в исходные байты. Каждые 4 символа Base64 декодируются ровно в 3 байта. Схема существует потому, что многие транспортные уровни (электронная почта, HTTP-заголовки, JSON-поля) рассчитаны на текст, а не на сырые бинарные данные. Base64 не является шифрованием — закодированную строку можно тривиально декодировать без каких-либо ключей. Для защиты данных используется подпись (как в JWT) или шифрование поверх кодирования. Ниже показано, как выглядит полный цикл кодирования и обратно:

Go 1.21+
package main

import (
	"encoding/base64"
	"fmt"
)

func main() {
	// Raw bytes → Base64 encoded → decoded back to raw bytes
	original := []byte("service_token:xK9mP2qR")
	// Encoded: "c2VydmljZV90b2tlbjp4SzltUDJxUg=="

	encoded := base64.StdEncoding.EncodeToString(original)
	decoded, _ := base64.StdEncoding.DecodeString(encoded)
	fmt.Println(string(decoded) == string(original)) // true
}

Декодирование Base64 в Go с помощью encoding/base64

Пакет encoding/base64 поставляется вместе с Go — никаких внешних зависимостей. Он предоставляет четыре предопределённых варианта кодировки в виде переменных уровня пакета. Наиболее часто используемая функция для строкового ввода — DecodeString, которая возвращает слайс байт и ошибку. В отличие от некоторых других языков, где функция просто возвращает nil при некорректном вводе, Go явно сигнализирует об ошибке — это позволяет точно определить позицию байта, вызвавшую сбой, что существенно упрощает отладку.

Go 1.21+
package main

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

func main() {
	// Standard Base64 — the alphabet uses + and / with = padding
	encoded := "eyJob3N0IjoiZGItcHJvZC51cy1lYXN0LTEiLCJwb3J0Ijo1NDMyfQ=="
	decoded, err := base64.StdEncoding.DecodeString(encoded)
	if err != nil {
		log.Fatalf("decode error: %v", err)
	}
	fmt.Println(string(decoded))
	// {"host":"db-prod.us-east-1","port":5432}
}

Метод Decode работает со слайсами байт, а не со строками, и записывает результат в заранее выделенный буфер назначения. Буфер нужно правильно размерить — используйте base64.StdEncoding.DecodedLen(len(src)), чтобы получить максимальный размер (он может быть на несколько байт больше фактической длины декодированных данных из-за паддинга).

Go 1.21+
package main

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

func main() {
	src := []byte("eyJob3N0IjoiZGItcHJvZCIsInBvcnQiOjU0MzJ9")
	dst := make([]byte, base64.RawStdEncoding.DecodedLen(len(src)))

	n, err := base64.RawStdEncoding.Decode(dst, src)
	if err != nil {
		log.Fatalf("decode: %v", err)
	}
	fmt.Println(string(dst[:n]))
	// {"host":"db-prod","port":5432}
}
Примечание:DecodedLen возвращает верхнюю границу, а не точную длину. Всегда используйте возвращаемое значение n из Decode для правильной нарезки результата: dst[:n].

StdEncoding vs URLEncoding — выбор правильного варианта

Именно здесь чаще всего возникает путаница. encoding/base64 в Go предоставляет четыре объекта кодировки, и выбор неправильного гарантированно приведёт к ошибке. Разница сводится к двум вещам: алфавиту и паддингу.

Go 1.21+
package main

import (
	"encoding/base64"
	"fmt"
)

func main() {
	// JWT header payload — URL-safe, no padding
	jwtHeader := "eyJhbGciOiJSUzI1NiIsImtpZCI6IjIwMjMtMDkifQ"

	// Wrong: StdEncoding fails on URL-safe input without padding
	_, err1 := base64.StdEncoding.DecodeString(jwtHeader)
	fmt.Println("StdEncoding error:", err1)
	// StdEncoding error: illegal base64 data at input byte 43

	// Correct: RawURLEncoding — no padding, URL-safe alphabet
	decoded, err2 := base64.RawURLEncoding.DecodeString(jwtHeader)
	fmt.Println("RawURLEncoding ok:", err2, "→", string(decoded))
	// RawURLEncoding ok: <nil> → {"alg":"RS256","kid":"2023-09"}
}

Четыре варианта простыми словами:

Функция / Метод
Кодировка
Обязателен паддинг
Возвращает
base64.StdEncoding.DecodeString(s)
Стандартная (+, /)
Да (=)
([]byte, error)
base64.URLEncoding.DecodeString(s)
URL-safe (-, _)
Да (=)
([]byte, error)
base64.RawStdEncoding.DecodeString(s)
Стандартная (+, /)
Нет
([]byte, error)
base64.RawURLEncoding.DecodeString(s)
URL-safe (-, _)
Нет
([]byte, error)
base64.StdEncoding.Decode(dst, src)
Стандартная (+, /)
Да (=)
(n int, error)
base64.NewDecoder(enc, r)
Любая кодировка
Да
io.Reader

Моё практическое правило: если данные пришли из JWT, OAuth-потока или SDK облачного провайдера, сначала пробуйте RawURLEncoding. Если источник — вложения электронной почты или старые веб-формы, попробуйте StdEncoding. Сообщение об ошибке всегда указывает точную позицию байта, на которой декодирование завершилось неудачей.

Декодирование Base64 из файла и ответа API

Чтение Base64-закодированного файла

Бинарные файлы (изображения, PDF, сертификаты) иногда хранятся на диске в Base64-кодировке. Прочитайте файл, удалите завершающие пробельные символы, затем декодируйте:

Go 1.21+
package main

import (
	"encoding/base64"
	"fmt"
	"log"
	"os"
	"strings"
)

func main() {
	raw, err := os.ReadFile("certificate.pem.b64")
	if err != nil {
		log.Fatalf("read file: %v", err)
	}

	// Strip newlines — Base64 files often have line breaks every 76 chars
	cleaned := strings.ReplaceAll(strings.TrimSpace(string(raw)), "\n", "")

	decoded, err := base64.StdEncoding.DecodeString(cleaned)
	if err != nil {
		log.Fatalf("decode: %v", err)
	}

	if err := os.WriteFile("certificate.pem", decoded, 0600); err != nil {
		log.Fatalf("write: %v", err)
	}
	fmt.Printf("decoded %d bytes → certificate.pem\n", len(decoded))
}

Декодирование поля Base64 из JSON-ответа API

Облачные API часто возвращают бинарные данные (ключи шифрования, подписанные блобы, миниатюры) в виде Base64-строк внутри JSON. Сначала распарсите JSON, затем декодируйте нужное поле:

Go 1.21+
package main

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

type SecretResponse struct {
	Name    string `json:"name"`
	Payload string `json:"payload"` // Base64-encoded secret value
	Version int    `json:"version"`
}

func fetchAndDecodeSecret(secretURL string) ([]byte, error) {
	resp, err := http.Get(secretURL)
	if err != nil {
		return nil, fmt.Errorf("http get: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unexpected status: %d", resp.StatusCode)
	}

	var secret SecretResponse
	if err := json.NewDecoder(resp.Body).Decode(&secret); err != nil {
		return nil, fmt.Errorf("decode json: %w", err)
	}

	value, err := base64.StdEncoding.DecodeString(secret.Payload)
	if err != nil {
		return nil, fmt.Errorf("decode base64: %w", err)
	}
	return value, nil
}

func main() {
	value, err := fetchAndDecodeSecret("https://api.example.com/secrets/db-password")
	if err != nil {
		log.Fatalf("fetch secret: %v", err)
	}
	fmt.Printf("secret value: %s\n", value)
}
Примечание:Оборачивайте ошибки через fmt.Errorf("decode base64: %w", err), а не теряйте контекст. Исходное сообщение об ошибке от encoding/base64 содержит позицию байта сбоя, что полезно при отладке.

Потоковое декодирование больших Base64-файлов

Загрузка 500 МБ Base64-файла в память через os.ReadFile с последующим вызовом DecodeString потребует около 750 МБ оперативной памяти (закодированная строка плюс декодированные байты). base64.NewDecoder оборачивает любой io.Reader и декодирует данные по частям, поддерживая потребление памяти практически постоянным. Это особенно актуально в контейнерных окружениях с жёсткими лимитами на RAM: потоковое декодирование позволяет обрабатывать файлы любого размера в рамках фиксированного бюджета памяти. Комбинируйте его с io.Copy для чистого потокового пайплайна:

Go 1.21+
package main

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

func streamDecodeFile(srcPath, dstPath string) error {
	src, err := os.Open(srcPath)
	if err != nil {
		return fmt.Errorf("open source: %w", err)
	}
	defer src.Close()

	dst, err := os.Create(dstPath)
	if err != nil {
		return fmt.Errorf("create dest: %w", err)
	}
	defer dst.Close()

	decoder := base64.NewDecoder(base64.StdEncoding, src)
	written, err := io.Copy(dst, decoder)
	if err != nil {
		return fmt.Errorf("stream decode: %w", err)
	}
	fmt.Printf("written %d bytes to %s\n", written, dstPath)
	return nil
}

func main() {
	if err := streamDecodeFile("backup.tar.b64", "backup.tar"); err != nil {
		log.Fatal(err)
	}
}
Предупреждение:base64.NewDecoder ожидает чистые, непрерывные данные Base64. Если в исходном файле есть переносы строк (характерно для PEM и MIME-файлов), оберните ридер в строко-фильтрующий ридер или предварительно удалите переносы строк из файла перед стримингом.

Декодирование Base64 из командной строки

Большинство Go-разработчиков при отладке первым делом обращаются к командной строке. На каждом macOS и Linux установлена утилита base64; в Windows PowerShell есть встроенный аналог. Для быстрой инспекции API-payload это быстрее, чем писать Go-скрипт.

bash
# Decode a Base64 string (Linux / macOS)
echo "eyJob3N0IjoiZGItcHJvZCIsInBvcnQiOjU0MzJ9" | base64 --decode
# {"host":"db-prod","port":5432}

# Decode and pretty-print with jq (pipe the JSON output)
echo "eyJob3N0IjoiZGItcHJvZCIsInBvcnQiOjU0MzJ9" | base64 --decode | jq .
# {
#   "host": "db-prod",
#   "port": 5432
# }

# Decode a Base64-encoded file to binary
base64 --decode < encrypted_payload.b64 > encrypted_payload.bin

# macOS uses -D flag instead of --decode
echo "c2VjcmV0LXRva2Vu" | base64 -D

Для инспекции JWT-токенов без установки каких-либо инструментов вставьте токен в Base64 Decoder от ToolDeck — разбейте по точкам и декодируйте каждую часть.

Высокопроизводительная альтернатива: encoding/base64 уже достаточно быстр

В отличие от Python, где разница между orjson и json — серьёзный разговор о производительности, encoding/base64 в Go уже оптимизирован на уровне ассемблера и действительно быстр для большинства задач. Прежде чем добавлять внешнюю зависимость ради производительности, проверьте с помощью pprof, что Base64 действительно является узким местом — на практике чаще всего причиной задержки оказывается сетевой ввод-вывод или сериализация JSON, а не само кодирование. Тем не менее, если вы обрабатываете миллионы записей в плотном цикле, filippo.io/base64 обеспечивает SIMD-ускоренное декодирование с совместимым API.

bash
go get filippo.io/base64
Go 1.21+
package main

import (
	"fmt"
	"log"

	"filippo.io/base64"
)

func main() {
	// Drop-in replacement — same API as encoding/base64
	encoded := "eyJob3N0IjoiY2FjaGUtcHJvZCIsInBvcnQiOjYzNzl9"
	decoded, err := base64.StdEncoding.DecodeString(encoded)
	if err != nil {
		log.Fatalf("decode: %v", err)
	}
	fmt.Println(string(decoded))
	// {"host":"cache-prod","port":6379}
}

Выигрыш в производительности наиболее заметен на amd64 с поддержкой AVX2 — бенчмарки показывают прирост пропускной способности в 2–4 раза на больших входных данных. Для повседневного декодирования ответов API (несколько сотен байт за раз) достаточно стандартной библиотеки.

Декодирование Base64 JWT payload в Go

Инспекция JWT встречается практически в каждом бэкенд-сервисе. По моему опыту, большинство отладочных сессий сводится к вопросу “что на самом деле содержится в этом токене?” — и ответить на него можно без подключения полноценной JWT-библиотеки. Помните, что это декодирование без верификации подписи: вы читаете содержимое, но не подтверждаете подлинность токена. Для production-кода верификацию подписи необходимо выполнять отдельно. Токен состоит из трёх Base64url-закодированных сегментов, разделённых точками. Средний сегмент — это payload, который нас интересует:

Go 1.21+
package main

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"strings"
)

type JWTPayload struct {
	Subject  string   `json:"sub"`
	Issuer   string   `json:"iss"`
	Expiry   int64    `json:"exp"`
	Roles    []string `json:"roles"`
}

func decodeJWTPayload(token string) (*JWTPayload, error) {
	parts := strings.Split(token, ".")
	if len(parts) != 3 {
		return nil, fmt.Errorf("invalid JWT: expected 3 segments, got %d", len(parts))
	}

	// JWT uses RawURLEncoding — URL-safe alphabet, no = padding
	raw, err := base64.RawURLEncoding.DecodeString(parts[1])
	if err != nil {
		return nil, fmt.Errorf("decode payload: %w", err)
	}

	var payload JWTPayload
	if err := json.Unmarshal(raw, &payload); err != nil {
		return nil, fmt.Errorf("unmarshal payload: %w", err)
	}
	return &payload, nil
}

func main() {
	token := "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c3ItNDQyIiwiaXNzIjoiYXV0aC5leGFtcGxlLmNvbSIsImV4cCI6MTc0MTk1NjgwMCwicm9sZXMiOlsiYWRtaW4iLCJhdWRpdG9yIl19.SIGNATURE"

	payload, err := decodeJWTPayload(token)
	if err != nil {
		log.Fatalf("jwt: %v", err)
	}
	fmt.Printf("Subject: %s\n", payload.Subject)
	fmt.Printf("Issuer:  %s\n", payload.Issuer)
	fmt.Printf("Roles:   %v\n", payload.Roles)
	// Subject: usr-442
	// Issuer:  auth.example.com
	// Roles:   [admin auditor]
}

Типичные ошибки

Все четыре из них я встречал в реальных код-ревью — первые два попадаются почти каждый раз, когда кто-то интегрирует нового провайдера аутентификации. Интересно, что ошибки третьего и четвёртого типа чаще всего появляются при миграции кода с Python или JavaScript: разработчики привыкают к неявному trim и безопасному преобразованию строк и забывают, что в Go это нужно делать явно.

Использование StdEncoding на URL-safe входных данных

Проблема: JWT-токены и OAuth-токены используют URL-safe алфавит Base64 (- и _). Передача их в StdEncoding.DecodeString завершается ошибкой 'illegal base64 data'.

Решение: Проверьте источник входных данных: токены от систем аутентификации требуют RawURLEncoding; бинарные вложения — StdEncoding.

Before · Go
After · Go
// JWT header — URL-safe, no padding
token := "eyJhbGciOiJSUzI1NiJ9"
decoded, err := base64.StdEncoding.DecodeString(token)
// err: illegal base64 data at input byte 19
// JWT header — correct encoding
token := "eyJhbGciOiJSUzI1NiJ9"
decoded, err := base64.RawURLEncoding.DecodeString(token)
// decoded: {"alg":"RS256"}
// err: nil
Игнорирование возвращаемого значения n из Decode

Проблема: Decode записывает данные в заранее выделенный буфер и возвращает фактическое количество записанных байт. DecodedLen возвращает верхнюю границу, поэтому хвост буфера может содержать мусорные байты.

Решение: Всегда нарезайте результат через dst[:n], а не dst[:len(dst)].

Before · Go
After · Go
dst := make([]byte, base64.StdEncoding.DecodedLen(len(src)))
base64.StdEncoding.Decode(dst, src)
fmt.Println(string(dst)) // may include trailing zero bytes
dst := make([]byte, base64.StdEncoding.DecodedLen(len(src)))
n, err := base64.StdEncoding.Decode(dst, src)
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(dst[:n])) // correct — only the decoded bytes
Отсутствие удаления пробельных символов перед декодированием

Проблема: Строки Base64, скопированные из терминалов, писем или конфигурационных файлов, часто содержат завершающие переносы строк или пробелы. Передача их напрямую в DecodeString завершается ошибкой на символе пробела.

Решение: Вызывайте strings.TrimSpace (и strings.ReplaceAll для встроенных переносов строк) перед декодированием.

Before · Go
After · Go
// Value read from a config file with a trailing newline
encoded := "c2VydmljZV9rZXk6eEtNcDI=\n"
decoded, err := base64.StdEncoding.DecodeString(encoded)
// err: illegal base64 data at input byte 24
encoded := "c2VydmljZV9rZXk6eEtNcDI=\n"
cleaned := strings.TrimSpace(encoded)
decoded, err := base64.StdEncoding.DecodeString(cleaned)
// decoded: "service_key:xKMp2"
// err: nil
Неправильное хранение декодированных байт в строке

Проблема: Вызов string(decoded) на бинарных данных (изображения, сжатые payload) создаёт невалидные UTF-8 строки. Go-строки могут хранить произвольные байты, но некоторые операции могут повредить содержимое.

Решение: Храните бинарные данные как []byte на протяжении всего пайплайна. Вызывайте string(decoded) только когда декодированное содержимое гарантированно является текстом.

Before · Go
After · Go
decoded, _ := base64.StdEncoding.DecodeString(pngBase64)
// Treating binary PNG as a string loses data
imageStr := string(decoded)
os.WriteFile("image.png", []byte(imageStr), 0644) // may corrupt
decoded, err := base64.StdEncoding.DecodeString(pngBase64)
if err != nil {
    log.Fatal(err)
}
// Write bytes directly — no string conversion
os.WriteFile("image.png", decoded, 0644)

Сравнение методов

Все варианты входят в стандартную библиотеку — никаких внешних зависимостей для любого из них. Выбор сводится к двум вопросам: откуда пришли данные и содержат ли они паддинг. Как только вы ответили на эти вопросы, нужный вариант определяется однозначно. Практическое правило: данные от JWT, OAuth и современных облачных API (AWS, Google Cloud, Azure) почти всегда используют RawURLEncoding. Данные из MIME-вложений электронной почты и устаревших веб-форм — StdEncoding. Если источник неизвестен, попробуйте RawURLEncodingпервым, поскольку большинство новых API следует этому стандарту. Для нестандартных алфавитов base64.NewEncoding(alphabet) создаёт объект кодировки с произвольными символами — редкий, но реальный сценарий при интеграции с устаревшими системами.

Метод
Тип входных данных
Варианты кодировки
Стриминг
Свой алфавит
Свой паддинг
Требует установки
StdEncoding.DecodeString
string
Стандартная
Нет (stdlib)
URLEncoding.DecodeString
string
URL-safe
Нет (stdlib)
RawStdEncoding.DecodeString
string
Стандартная (без паддинга)
Нет (stdlib)
RawURLEncoding.DecodeString
string
URL-safe (без паддинга)
Нет (stdlib)
StdEncoding.Decode
[]byte
Стандартная
Нет (stdlib)
base64.NewDecoder
io.Reader
Любая
Нет (stdlib)
encoding/base64 + NewEncoding
string
Свой алфавит
Нет (stdlib)

Для JWT-токенов и OAuth-потоков: RawURLEncoding. Для вложений электронной почты и MIME-данных: StdEncoding. Для больших бинарных файлов с диска или сети: оберните ридер в base64.NewDecoder — потребление памяти останется постоянным независимо от размера файла. Нужен свой алфавит? base64.NewEncoding(alphabet) создаёт новый объект кодировки для нестандартных случаев.

Для быстрых разовых проверок в процессе разработки онлайн Base64 Decoder быстрее, чем запускать Go-программу.

Часто задаваемые вопросы

Как декодировать строку Base64 в Go?

Импортируйте encoding/base64 и вызовите base64.StdEncoding.DecodeString(s). Функция возвращает ([]byte, error) — всегда проверяйте ошибку. Если строка использует URL-safe символы (- и _ вместо + и /), используйте base64.URLEncoding.DecodeString. Для JWT-токенов и большинства современных API правильный выбор — RawURLEncoding (без паддинга).

Go 1.21+
package main

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

func main() {
	encoded := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9"
	decoded, err := base64.RawURLEncoding.DecodeString(encoded)
	if err != nil {
		log.Fatalf("decode: %v", err)
	}
	fmt.Println(string(decoded))
	// {"alg":"HS256","typ":"JWT"}
}

В чём разница между StdEncoding и URLEncoding в Go?

StdEncoding использует стандартный алфавит Base64 с символами + и / и паддингом = — определено в RFC 4648 §4. URLEncoding заменяет + на - и / на _, делая вывод безопасным в URL и HTTP-заголовках без percent-encoding — определено в RFC 4648 §5. Используйте URLEncoding для JWT-токенов, OAuth-токенов и любых данных, встраиваемых в строки запроса.

Go 1.21+
package main

import (
	"encoding/base64"
	"fmt"
)

func main() {
	// Standard: may contain + / and = characters
	std := base64.StdEncoding.EncodeToString([]byte("hello/world"))
	fmt.Println(std) // "aGVsbG8vd29ybGQ="

	// URL-safe: replaces + with - and / with _
	url := base64.URLEncoding.EncodeToString([]byte("hello/world"))
	fmt.Println(url) // "aGVsbG8vd29ybGQ=" (same — diff shows with different bytes)

	// JWT headers never have padding — use RawURLEncoding
	raw := base64.RawURLEncoding.EncodeToString([]byte("hello/world"))
	fmt.Println(raw) // "aGVsbG8vd29ybGQ" (no trailing =)
}

Как исправить ошибки "illegal base64 data" в Go?

Эта ошибка означает, что входные данные содержат символы за пределами ожидаемого алфавита, либо паддинг задан неверно. Три распространённые причины: использование StdEncoding на URL-safe входных данных (замените на URLEncoding), использование кодировщика с паддингом на данных без паддинга (замените на RawStdEncoding/RawURLEncoding), или наличие пробельных символов/переносов строк. Удалите пробельные символы с помощью strings.TrimSpace перед декодированием.

Go 1.21+
package main

import (
	"encoding/base64"
	"fmt"
	"log"
	"strings"
)

func main() {
	// Input from a webhook payload — has newlines stripped from wire format
	raw := "  aGVsbG8gd29ybGQ=  \n"
	cleaned := strings.TrimSpace(raw)

	decoded, err := base64.StdEncoding.DecodeString(cleaned)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(decoded)) // hello world
}

Как стримингово декодировать большой Base64-файл в Go?

Используйте base64.NewDecoder(base64.StdEncoding, reader), который оборачивает любой io.Reader и декодирует данные на лету. Передайте его в io.Copy для записи в назначение без буферизации всего файла в памяти. Это стандартный паттерн для декодирования Base64-закодированных бинарных вложений или больших данных.

Go 1.21+
package main

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

func main() {
	src, err := os.Open("attachment.b64")
	if err != nil {
		log.Fatal(err)
	}
	defer src.Close()

	dst, err := os.Create("attachment.bin")
	if err != nil {
		log.Fatal(err)
	}
	defer dst.Close()

	decoder := base64.NewDecoder(base64.StdEncoding, src)
	io.Copy(dst, decoder)
}

Можно ли декодировать Base64 JWT payload в Go без JWT-библиотеки?

Да. JWT — это три Base64url-закодированных сегмента, разделённых точками. Разбейте токен по "." и декодируйте второй сегмент (индекс 1) с помощью base64.RawURLEncoding.DecodeString — заголовки и payload JWT используют URL-safe алфавит и не содержат паддинга. Сегмент подписи (индекс 2) является бинарным и обычно нужен только для верификации.

Go 1.21+
package main

import (
	"encoding/base64"
	"fmt"
	"log"
	"strings"
)

func main() {
	token := "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c3ItOTAxIiwicm9sZSI6ImFkbWluIn0.SIG"
	parts := strings.Split(token, ".")
	if len(parts) < 2 {
		log.Fatal("invalid JWT format")
	}

	payload, err := base64.RawURLEncoding.DecodeString(parts[1])
	if err != nil {
		log.Fatalf("decode payload: %v", err)
	}
	fmt.Println(string(payload))
	// {"sub":"usr-901","role":"admin"}
}

Какую кодировку использовать для декодирования Base64 из ответа HTTP API?

Проверьте документацию API или осмотрите закодированную строку. Если она содержит символы + или / и заканчивается на =, используйте StdEncoding. Если в ней символы - и _ без =, используйте RawURLEncoding. В случае неопределённости сначала попробуйте RawURLEncoding — большинство современных API (OAuth2, JWT, Google Cloud, AWS) используют URL-safe Base64 без паддинга.

Go 1.21+
package main

import (
	"encoding/base64"
	"strings"
)

// Detect encoding variant from the encoded string
func decodeAPIPayload(encoded string) ([]byte, error) {
	// URL-safe characters without padding — common in modern APIs
	if !strings.Contains(encoded, "+") && !strings.Contains(encoded, "/") {
		return base64.RawURLEncoding.DecodeString(encoded)
	}
	// Standard Base64 with padding
	return base64.StdEncoding.DecodeString(encoded)
}

Связанные инструменты

  • Base64 Encoder — закодируйте бинарные данные или текст в Base64 прямо в браузере, удобно для генерации тестовых фикстур, которые можно вставить в юнит-тесты Go.
  • JWT Decoder — разбейте и декодируйте все три сегмента JWT одновременно с пофилдовой инспекцией payload — никакого Go-кода не нужно, когда во время отладки достаточно просто прочитать токен.
  • URL Decoder — декодируйте percent-encoded URL-строки, полезно когда ответы API смешивают Base64url данные с percent-encoded параметрами запроса.
  • JSON Formatter — после декодирования Base64 JWT payload или ответа API вставьте JSON сюда для форматирования и мгновенной проверки структуры.
Также доступно на:JavaScriptPythonJavaC#
JO
James OkaforSystems Engineer

James is a systems engineer and Go enthusiast who focuses on high-performance microservices, command-line tooling, and infrastructure automation. He enjoys the simplicity and explicitness of Go and writes about building fast, reliable backend systems. When not coding he explores distributed systems concepts and contributes to open-source Go libraries.

HN
Hana NovákováТехнический рецензент

Hana is a backend engineer who has built production gRPC and REST services in Go for cloud-native environments. She cares deeply about API correctness, protobuf schema design, and the operational side of running Go services in Kubernetes. She writes about the Go standard library, encoding and marshalling patterns, gRPC best practices, and the subtleties of writing idiomatic Go that is easy to test and maintain.