Giải mã Base64 trong Go xuất hiện liên tục — kiểm tra JWT, file đính kèm nhị phân, payload API từ các dịch vụ đám mây. Package encoding/base64trong thư viện chuẩn của Go xử lý tất cả điều đó, nhưng chọn sai biến thể bảng mã (chuẩn so với URL-safe, có padding so với không padding) là nguồn gốc phổ biến nhất của lỗi “illegal base64 data”. Hướng dẫn này đề cập đến tất cả biến thể bảng mã, giải mã streaming và bốn lỗi phổ biến. Để giải mã nhanh trên trình duyệt, công cụ Giải mã Base64 của ToolDeck cho kết quả ngay lập tức mà không cần viết một dòng code nào.
- ✓encoding/base64 là một phần của thư viện chuẩn Go — không cần go get
- ✓Dùng RawURLEncoding cho JWT token và hầu hết API hiện đại (không padding, bảng chữ cái URL-safe)
- ✓StdEncoding dùng + và / với padding =; URLEncoding đổi sang - và _ nhưng vẫn giữ padding
- ✓base64.NewDecoder bọc bất kỳ io.Reader nào để giải mã streaming mà không cần tải vào bộ nhớ
- ✓Luôn kiểm tra lỗi trả về — padding sai và bảng chữ cái không đúng đều tạo ra lỗi illegal base64 data
Giải mã Base64 là gì?
Mã hóa Base64 biểu diễn dữ liệu nhị phân dưới dạng văn bản ASCII sử dụng 64 ký tự in được (A–Z, a–z, 0–9 và hai ký tự bổ sung). Giải mã thực hiện ngược lại — chuyển đổi biểu diễn ASCII đó trở lại thành các byte gốc. Cứ 4 ký tự Base64 giải mã thành đúng 3 byte. Cơ chế này tồn tại vì nhiều tầng truyền tải (email, HTTP header, trường JSON) được thiết kế cho văn bản, không phải nhị phân thô. Dưới đây là quá trình khứ hồi trông như thế nào:
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
}Giải mã Base64 trong Go với encoding/base64
Package encoding/base64 được tích hợp sẵn trong Go — không cần phụ thuộc ngoài. Nó cung cấp bốn biến thể bảng mã được định nghĩa sẵn dưới dạng biến cấp package. Hàm được dùng phổ biến nhất cho đầu vào chuỗi là DecodeString, trả về một byte slice và một error.
package main
import (
"encoding/base64"
"fmt"
"log"
)
func main() {
// Base64 chuẩn — bảng chữ cái dùng + và / với padding =
encoded := "eyJob3N0IjoiZGItcHJvZCF1cy1lYXN0LTEiLCJwb3J0Ijo1NDMyfQ=="
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}
}Phương thức Decode hoạt động trên byte slice thay vì chuỗi, và ghi kết quả vào buffer đích được cấp phát trước. Bạn cần định kích thước buffer chính xác — dùng base64.StdEncoding.DecodedLen(len(src)) để lấy kích thước tối đa (có thể lớn hơn độ dài giải mã thực tế vài byte do padding).
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 trả về giới hạn trên, không phải độ dài chính xác. Luôn dùng giá trị trả về n từ Decode để cắt kết quả đúng cách: dst[:n].StdEncoding và URLEncoding — Chọn biến thể đúng
Đây là nguồn gốc gây nhầm lẫn nhiều nhất. encoding/base64 của Go cung cấp bốn đối tượng bảng mã, và chọn sai một cái chắc chắn sẽ cho bạn lỗi. Sự khác biệt nằm ở hai điểm: bảng chữ cái và padding.
package main
import (
"encoding/base64"
"fmt"
)
func main() {
// JWT header payload — URL-safe, không padding
jwtHeader := "eyJhbGciOiJSUzI1NiIsImtpZCI6IjIwMjMtMDkifQ"
// Sai: StdEncoding thất bại với đầu vào URL-safe không có padding
_, err1 := base64.StdEncoding.DecodeString(jwtHeader)
fmt.Println("StdEncoding error:", err1)
// StdEncoding error: illegal base64 data at input byte 43
// Đúng: RawURLEncoding — không padding, bảng chữ cái URL-safe
decoded, err2 := base64.RawURLEncoding.DecodeString(jwtHeader)
fmt.Println("RawURLEncoding ok:", err2, "→", string(decoded))
// RawURLEncoding ok: <nil> → {"alg":"RS256","kid":"2023-09"}
}Bốn biến thể theo cách diễn đạt đơn giản:
Quy tắc ngón tay cái của tôi: nếu dữ liệu đến từ JWT, OAuth flow, hoặc SDK của nhà cung cấp đám mây, hãy dùng RawURLEncoding trước. Nếu từ file đính kèm email hoặc form web kiểu cũ, thử StdEncoding. Thông báo lỗi luôn cho bạn biết vị trí byte chính xác nơi giải mã thất bại.
Giải mã Base64 từ File và Phản hồi API
Đọc file được mã hóa Base64
Các file nhị phân (hình ảnh, PDF, chứng chỉ) đôi khi được lưu trữ dưới dạng mã hóa Base64 trên đĩa. Đọc file, loại bỏ khoảng trắng cuối, rồi giải mã:
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)
}
// Loại bỏ ký tự xuống dòng — file Base64 thường có ngắt dòng mỗi 76 ký tự
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))
}Giải mã trường Base64 từ phản hồi JSON của API
Các API đám mây thường trả về dữ liệu nhị phân (khóa mã hóa, blob đã ký, thumbnail) dưới dạng chuỗi Base64 bên trong JSON. Giải nén JSON trước, rồi giải mã trường mục tiêu:
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
"log"
"net/http"
)
type SecretResponse struct {
Name string `json:"name"`
Payload string `json:"payload"` // Giá trị bí mật được mã hóa Base64
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) thay vì mất ngữ cảnh. Thông báo lỗi gốc từ encoding/base64 bao gồm vị trí byte nơi xảy ra lỗi, rất hữu ích khi debug.Giải mã Streaming các File Base64 Lớn
Tải file Base64 500 MB vào bộ nhớ bằng os.ReadFile rồi gọi DecodeString sử dụng khoảng 750 MB RAM (chuỗi đã mã hóa cộng với các byte đã giải mã). base64.NewDecoder bọc bất kỳ io.Reader nào và giải mã theo từng chunk, giữ mức sử dụng bộ nhớ gần như không đổi. Kết hợp với io.Copy để tạo pipeline streaming gọn gàng:
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 yêu cầu dữ liệu Base64 sạch, không bị ngắt quãng. Nếu file nguồn có ngắt dòng (phổ biến trong file PEM và MIME-encoded), hãy bọc reader nguồn bằng một reader loại bỏ dòng hoặc tiền xử lý file để xóa ký tự xuống dòng trước khi streaming.Giải mã Base64 từ Dòng lệnh
Hầu hết lập trình viên Go thường dùng dòng lệnh trước khi debug. Mọi hệ thống macOS và Linux đều có sẵn lệnh base64; trên Windows, PowerShell có lệnh tương đương tích hợp. Để kiểm tra nhanh API payload, các lệnh này nhanh hơn viết script Go.
# Giải mã chuỗi Base64 (Linux / macOS)
echo "eyJob3N0IjoiZGItcHJvZCIsInBvcnQiOjU0MzJ9" | base64 --decode
# {"host":"db-prod","port":5432}
# Giải mã và in đẹp với jq (pipe đầu ra JSON)
echo "eyJob3N0IjoiZGItcHJvZCIsInBvcnQiOjU0MzJ9" | base64 --decode | jq .
# {
# "host": "db-prod",
# "port": 5432
# }
# Giải mã file mã hóa Base64 sang nhị phân
base64 --decode < encrypted_payload.b64 > encrypted_payload.bin
# macOS dùng flag -D thay vì --decode
echo "c2VjcmV0LXRva2Vu" | base64 -DĐể kiểm tra JWT token mà không cần cài đặt công cụ nào, dán token vào công cụ Giải mã Base64 của ToolDeck — tách theo dấu chấm và giải mã từng phần.
Giải pháp hiệu năng cao: encoding/base64 đã đủ nhanh
Không giống Python, nơi orjson so với json là cuộc tranh luận hiệu năng có ý nghĩa, encoding/base64 của Go đã được tối ưu hóa bằng assembly và thực sự nhanh cho hầu hết khối lượng công việc. Tuy nhiên, nếu bạn đang xử lý hàng triệu bản ghi trong vòng lặp chặt, filippo.io/base64 cung cấp giải mã tăng tốc SIMD với API tương thích trực tiếp.
go get filippo.io/base64
package main
import (
"fmt"
"log"
"filippo.io/base64"
)
func main() {
// Thay thế trực tiếp — cùng API với 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}
}Lợi ích hiệu năng rõ ràng nhất trên amd64 với hỗ trợ AVX2 — benchmark cho thấy cải thiện thông lượng 2–4x trên đầu vào lớn. Để giải mã phản hồi API hằng ngày (vài trăm byte mỗi lần), hãy dùng thư viện chuẩn.
Giải mã Payload JWT Base64 trong Go
Kiểm tra JWT xuất hiện trong hầu hết mọi dịch vụ backend. Theo kinh nghiệm của tôi, hầu hết phiên debug đều quy về câu hỏi “token này thực sự chứa gì?” — và bạn có thể trả lời mà không cần đưa vào thư viện JWT đầy đủ. Token có ba đoạn mã hóa Base64url được phân tách bởi dấu chấm. Đoạn giữa là payload mà bạn thực sự cần:
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 dùng RawURLEncoding — bảng chữ cái URL-safe, không 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]
}Lỗi Thường Gặp
Tôi đã gặp cả bốn lỗi này trong các code review thực tế — hai lỗi đầu đặc biệt xuất hiện hầu như mỗi lần ai đó tích hợp auth provider mới.
Vấn đề: JWT token và OAuth token dùng bảng chữ cái Base64 URL-safe (- và _). Truyền chúng vào StdEncoding.DecodeString sẽ thất bại với lỗi 'illegal base64 data'.
Giải pháp: Kiểm tra nguồn đầu vào: token từ hệ thống auth dùng RawURLEncoding; file đính kèm nhị phân dùng StdEncoding.
// JWT header — URL-safe, không padding token := "eyJhbGciOiJSUzI1NiJ9" decoded, err := base64.StdEncoding.DecodeString(token) // err: illegal base64 data at input byte 19
// JWT header — bảng mã đúng
token := "eyJhbGciOiJSUzI1NiJ9"
decoded, err := base64.RawURLEncoding.DecodeString(token)
// decoded: {"alg":"RS256"}
// err: nilVấn đề: Decode ghi vào buffer được cấp phát trước và trả về số byte thực sự được ghi. DecodedLen trả về giới hạn trên, nên phần cuối buffer có thể chứa byte rác.
Giải pháp: Luôn cắt kết quả với dst[:n] — không phải dst[:len(dst)].
dst := make([]byte, base64.StdEncoding.DecodedLen(len(src))) base64.StdEncoding.Decode(dst, src) fmt.Println(string(dst)) // có thể bao gồm byte zero ở cuối
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])) // đúng — chỉ các byte đã giải mãVấn đề: Chuỗi Base64 được sao chép từ terminal, email, hoặc config file thường có ký tự xuống dòng hoặc khoảng trắng ở cuối. Truyền trực tiếp vào DecodeString sẽ thất bại tại ký tự khoảng trắng.
Giải pháp: Gọi strings.TrimSpace (và strings.ReplaceAll với ký tự xuống dòng nhúng) trước khi giải mã.
// Giá trị đọc từ config file có ký tự xuống dòng ở cuối 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
Vấn đề: Gọi string(decoded) trên dữ liệu nhị phân (hình ảnh, payload nén) tạo ra chuỗi UTF-8 không hợp lệ. Chuỗi Go có thể giữ byte tùy ý, nhưng một số thao tác sẽ làm hỏng nội dung.
Giải pháp: Giữ dữ liệu nhị phân dưới dạng []byte trong toàn bộ pipeline. Chỉ gọi string(decoded) khi nội dung giải mã được đảm bảo là văn bản.
decoded, _ := base64.StdEncoding.DecodeString(pngBase64)
// Xử lý PNG nhị phân như chuỗi sẽ mất dữ liệu
imageStr := string(decoded)
os.WriteFile("image.png", []byte(imageStr), 0644) // có thể bị hỏngdecoded, err := base64.StdEncoding.DecodeString(pngBase64)
if err != nil {
log.Fatal(err)
}
// Ghi byte trực tiếp — không chuyển đổi sang chuỗi
os.WriteFile("image.png", decoded, 0644)So sánh các Phương thức
Tất cả các biến thể đều có trong thư viện chuẩn — không cần phụ thuộc ngoài cho bất kỳ phương thức nào trong số này.
Cho JWT token và OAuth flow: RawURLEncoding. Cho file đính kèm email và dữ liệu MIME: StdEncoding. Cho file nhị phân lớn từ đĩa hoặc mạng: bọc reader trong base64.NewDecoder — giữ mức sử dụng bộ nhớ không đổi bất kể kích thước file. Cần bảng chữ cái tùy chỉnh? base64.NewEncoding(alphabet) tạo đối tượng bảng mã mới cho các trường hợp đặc biệt.
Để kiểm tra nhanh trong quá trình phát triển, công cụ Giải mã Base64 trực tuyến nhanh hơn khởi động một chương trình Go.
Câu hỏi Thường gặp
Làm thế nào để giải mã chuỗi Base64 trong Go?
Import encoding/base64 và gọi base64.StdEncoding.DecodeString(s). Hàm này trả về ([]byte, error) — luôn kiểm tra lỗi. Nếu chuỗi sử dụng ký tự URL-safe (- và _ thay vì + và /), dùng base64.URLEncoding.DecodeString. Với JWT token và hầu hết các API hiện đại, RawURLEncoding (không có padding) là lựa chọn đúng đắn.
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"}
}Sự khác biệt giữa StdEncoding và URLEncoding trong Go là gì?
StdEncoding sử dụng bảng chữ cái Base64 chuẩn với ký tự + và / cùng padding = — được định nghĩa trong RFC 4648 §4. URLEncoding thay + bằng - và / bằng _ để đầu ra an toàn trong URL và HTTP header mà không cần percent-encoding — được định nghĩa trong RFC 4648 §5. Dùng URLEncoding cho JWT token, OAuth token, và dữ liệu nhúng trong query string.
package main
import (
"encoding/base64"
"fmt"
)
func main() {
// Standard: có thể chứa ký tự + / và =
std := base64.StdEncoding.EncodeToString([]byte("hello/world"))
fmt.Println(std) // "aGVsbG8vd29ybGQ="
// URL-safe: thay + bằng - và / bằng _
url := base64.URLEncoding.EncodeToString([]byte("hello/world"))
fmt.Println(url) // "aGVsbG8vd29ybGQ=" (giống nhau — khác thể hiện khi byte khác nhau)
// JWT header không bao giờ có padding — dùng RawURLEncoding
raw := base64.RawURLEncoding.EncodeToString([]byte("hello/world"))
fmt.Println(raw) // "aGVsbG8vd29ybGQ" (không có = cuối)
}Làm thế nào để sửa lỗi "illegal base64 data" trong Go?
Lỗi này có nghĩa là đầu vào chứa ký tự ngoài bảng chữ cái mong đợi, hoặc padding sai. Ba nguyên nhân phổ biến: dùng StdEncoding trên đầu vào URL-safe (đổi sang URLEncoding), dùng encoder có padding trên đầu vào không có padding (đổi sang RawStdEncoding/RawURLEncoding), hoặc có khoảng trắng/ký tự xuống dòng ở cuối. Dùng strings.TrimSpace để loại bỏ khoảng trắng trước khi giải mã.
package main
import (
"encoding/base64"
"fmt"
"log"
"strings"
)
func main() {
// Đầu vào từ webhook payload — có ký tự xuống dòng bị loại bỏ khỏi 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
}Làm thế nào để giải mã streaming một file Base64 lớn trong Go?
Dùng base64.NewDecoder(base64.StdEncoding, reader) để bọc bất kỳ io.Reader nào và giải mã ngay khi đọc. Kết hợp với io.Copy để ghi vào đích mà không cần đưa toàn bộ file vào bộ nhớ. Đây là pattern chuẩn để giải mã các file đính kèm nhị phân hoặc payload dữ liệu lớn được mã hóa Base64.
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)
}Có thể giải mã payload Base64 JWT trong Go mà không cần thư viện JWT không?
Có. JWT là ba đoạn được mã hóa Base64url nối với nhau bằng dấu chấm. Tách theo "." và giải mã đoạn thứ hai (index 1) bằng base64.RawURLEncoding.DecodeString — JWT header và payload dùng bảng chữ cái URL-safe và không có padding. Đoạn chữ ký (index 2) là nhị phân và thường chỉ cần khi xác minh.
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"}
}Nên dùng bảng mã nào để giải mã dữ liệu Base64 từ phản hồi HTTP API?
Kiểm tra tài liệu API hoặc quan sát chuỗi được mã hóa. Nếu chứa ký tự + hoặc / và kết thúc bằng =, dùng StdEncoding. Nếu dùng ký tự - và _ không có =, dùng RawURLEncoding. Khi không chắc, thử RawURLEncoding trước — hầu hết các API hiện đại (OAuth2, JWT, Google Cloud, AWS) dùng Base64 URL-safe không có padding.
package main
import (
"encoding/base64"
"strings"
)
// Phát hiện biến thể bảng mã từ chuỗi được mã hóa
func decodeAPIPayload(encoded string) ([]byte, error) {
// Ký tự URL-safe không có padding — phổ biến trong các API hiện đại
if !strings.Contains(encoded, "+") && !strings.Contains(encoded, "/") {
return base64.RawURLEncoding.DecodeString(encoded)
}
// Base64 chuẩn có padding
return base64.StdEncoding.DecodeString(encoded)
}Công cụ Liên quan
- Mã hóa Base64 — mã hóa dữ liệu nhị phân hoặc văn bản sang Base64 trên trình duyệt, hữu ích để tạo test fixture dán vào unit test Go của bạn.
- Giải mã JWT — tách và giải mã cả ba đoạn JWT cùng lúc, với kiểm tra payload theo từng trường — không cần code Go khi bạn chỉ cần đọc token trong quá trình debug.
- Giải mã URL — giải mã percent-encode các chuỗi URL-encoded, tiện lợi khi phản hồi API kết hợp dữ liệu Base64url với các query parameter được percent-encode.
- Định dạng JSON — sau khi giải mã payload JWT Base64 hoặc phản hồi API, dán JSON vào đây để in đẹp và xác thực cấu trúc ngay lập tức.