ToolDeck

ถอดรหัส Base64 ใน Go — คู่มือ

·Systems Engineer·ตรวจสอบโดยHana Nováková·เผยแพร่เมื่อ

ใช้ ถอดรหัส Base64 ออนไลน์ ฟรีโดยตรงในเบราว์เซอร์ของคุณ — ไม่ต้องติดตั้ง

ลอง ถอดรหัส Base64 ออนไลน์ ออนไลน์ →

การถอดรหัส Base64 ใน Go พบได้บ่อยมาก — ไม่ว่าจะเป็นการตรวจสอบ JWT, ไฟล์แนบแบบ binary หรือ API payload จากบริการ cloud แพ็กเกจ encoding/base64มาตรฐานของ Go รองรับทั้งหมดนี้ แต่การเลือกรูปแบบการเข้ารหัสผิด (มาตรฐาน vs URL-safe, มี padding vs ไม่มี padding) คือสาเหตุหลักที่ทำให้เกิดข้อผิดพลาด “illegal base64 data” คู่มือนี้ครอบคลุม StdEncoding, URLEncoding, RawURLEncoding, การถอดรหัสแบบ streaming ด้วย base64.NewDecoder, การตรวจสอบ JWT payload และข้อผิดพลาด 4 ประการที่มักพบ สำหรับการถอดรหัสแบบรวดเร็วในเบราว์เซอร์ ตัวถอดรหัส Base64 ของ ToolDeck ช่วยได้ทันทีโดยไม่ต้องเขียนโค้ดแม้แต่บรรทัดเดียว

  • encoding/base64 เป็นส่วนหนึ่งของ Go standard library — ไม่ต้องใช้ go get
  • ใช้ RawURLEncoding สำหรับ JWT token และ API สมัยใหม่ส่วนใหญ่ (ไม่มี padding, alphabet แบบ URL-safe)
  • StdEncoding ใช้ + และ / พร้อม padding =; URLEncoding เปลี่ยนเป็น - และ _ แต่ยังคง padding ไว้
  • base64.NewDecoder ครอบ io.Reader ใด ๆ สำหรับการถอดรหัสแบบ streaming โดยไม่โหลดข้อมูลเข้าหน่วยความจำ
  • ตรวจสอบ error ที่คืนกลับมาเสมอ — padding ไม่ถูกต้องและ alphabet ผิดจะทำให้เกิด illegal base64 data

การถอดรหัส Base64 คืออะไร?

การเข้ารหัส Base64 แสดงข้อมูล binary เป็นข้อความ ASCII โดยใช้อักขระที่พิมพ์ได้ 64 ตัว (A–Z, a–z, 0–9, บวกอีกสองตัว) การถอดรหัสเป็นการย้อนกลับ — แปลงการแสดง ASCII กลับเป็น byte ต้นฉบับ อักขระ Base64 ทุก 4 ตัวถอดรหัสได้ 3 byte พอดี รูปแบบนี้มีอยู่เพราะ transport layer หลายชั้น (อีเมล, HTTP header, JSON field) ออกแบบมาสำหรับข้อความ ไม่ใช่ binary ดิบ ด้านล่างคือตัวอย่างการทำงานแบบ round-trip:

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 — ไม่มี dependency ภายนอก แพ็กเกจนี้เปิดเผยรูปแบบการเข้ารหัสที่กำหนดไว้ล่วงหน้า 4 แบบเป็น package-level variable ฟังก์ชันที่ใช้บ่อยที่สุดสำหรับ string input คือ DecodeStringซึ่งคืนค่าเป็น byte slice และ error

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 ทำงานกับ byte slice แทน string และเขียนผลลัพธ์ลงใน destination buffer ที่จัดสรรไว้ล่วงหน้า คุณต้องกำหนดขนาด buffer ให้ถูกต้อง — ใช้ base64.StdEncoding.DecodedLen(len(src)) เพื่อรับขนาดสูงสุด (อาจใหญ่กว่าความยาวที่ถอดรหัสจริงสองสามไบต์เนื่องจาก padding)

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 เพื่อตัด slice ให้ถูกต้อง: dst[:n]

StdEncoding vs URLEncoding — เลือกรูปแบบที่ถูกต้อง

นี่คือจุดที่สร้างความสับสนมากที่สุด encoding/base64 ของ Go มี encoding object 4 แบบ และการเลือกผิดแบบรับประกันว่าจะได้รับ error ความแตกต่างขึ้นอยู่กับสองสิ่ง: alphabet และ padding

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"}
}

4 รูปแบบในภาษาง่าย ๆ:

ฟังก์ชัน / เมธอด
การเข้ารหัส
ต้องมี Padding
ค่าที่คืนกลับ
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 flow หรือ cloud provider SDK ให้ลอง RawURLEncoding ก่อน ถ้ามาจากไฟล์แนบอีเมลหรือเว็บฟอร์มแบบเก่าให้ลอง StdEncoding ข้อความ error จะบอกตำแหน่ง byte ที่แน่นอนที่การถอดรหัสล้มเหลวเสมอ

ถอดรหัส Base64 จากไฟล์และ API Response

อ่านไฟล์ที่เข้ารหัส Base64

ไฟล์ binary (รูปภาพ, PDF, certificate) บางครั้งถูกเก็บในรูปแบบ Base64 บนดิสก์ อ่านไฟล์, ลบ whitespace ที่ท้าย แล้วถอดรหัส:

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

ถอดรหัส field Base64 จาก API JSON response

Cloud API มักคืนข้อมูล binary (encryption key, signed blob, thumbnail) เป็น string Base64 ภายใน JSON Unmarshal JSON ก่อน จากนั้นถอดรหัส field ที่ต้องการ:

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)
}
หมายเหตุ:ครอบ error ด้วย fmt.Errorf("decode base64: %w", err) แทนที่จะสูญเสีย context ข้อความ error ต้นฉบับจาก encoding/base64 รวมตำแหน่ง byte ที่เกิดความล้มเหลว ซึ่งมีประโยชน์มากระหว่างการ debug

Streaming ไฟล์ขนาดใหญ่ที่เข้ารหัส Base64

การโหลดไฟล์ที่เข้ารหัส Base64 ขนาด 500 MB เข้าหน่วยความจำด้วย os.ReadFile แล้วเรียก DecodeString ใช้ RAM ประมาณ 750 MB (encoded string บวก decoded bytes) base64.NewDecoder ครอบ io.Reader ใด ๆ และถอดรหัสเป็น chunk ทำให้การใช้ หน่วยความจำเกือบคงที่ ใช้ร่วมกับ io.Copy เพื่อ pipeline streaming ที่สะอาด:

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 ที่สะอาดและต่อเนื่อง ถ้าไฟล์ต้นทาง มี line break (พบบ่อยในไฟล์ PEM และ MIME-encoded) ให้ครอบ source reader ด้วย line-stripping reader หรือประมวลผลไฟล์ล่วงหน้าเพื่อลบ newline ก่อน streaming

ถอดรหัส Base64 จาก Command Line

นักพัฒนา Go ส่วนใหญ่ใช้ command line ก่อนเมื่อต้อง debug ทุกระบบ macOS และ Linux มาพร้อมกับคำสั่ง base64; บน Windows PowerShell มีฟีเจอร์ที่เทียบเท่ากัน สำหรับการตรวจสอบ API payload อย่างรวดเร็ว วิธีเหล่านี้เร็วกว่าการเขียน Go script

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 token โดยไม่ต้องติดตั้งเครื่องมือใด ๆ วาง token ลงใน ตัวถอดรหัส Base64 ของ ToolDeck — แยกด้วยจุดและถอดรหัสแต่ละส่วน

ทางเลือกประสิทธิภาพสูง: encoding/base64 เร็วอยู่แล้ว

ต่างจาก Python ที่ orjson vs json เป็นการสนทนาเรื่องประสิทธิภาพที่มีนัยสำคัญencoding/base64 ของ Go ถูก optimize ด้วย assembly และเร็วพอสำหรับ workload ส่วนใหญ่ อย่างไรก็ตาม หากคุณกำลังประมวลผล record หลายล้านรายการใน tight loop filippo.io/base64 ให้การถอดรหัสแบบ SIMD-accelerated พร้อม 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 — benchmark แสดงให้เห็นว่า throughput เพิ่มขึ้น 2–4 เท่าสำหรับ input ขนาดใหญ่ สำหรับการถอดรหัส API response ในชีวิตประจำวัน (ข้อมูลไม่กี่ร้อย byte ต่อครั้ง) ให้ใช้ standard library ก็เพียงพอแล้ว

ถอดรหัส JWT Payload แบบ Base64 ใน Go

การตรวจสอบ JWT พบได้ในแทบทุก backend service จากประสบการณ์ของผม session การ debug ส่วนใหญ่สรุปได้ว่า “จริง ๆ แล้วมีอะไรอยู่ใน token นี้?” — และคุณสามารถตอบได้ โดยไม่ต้องดึง JWT library เต็มรูปแบบมา Token มีสามส่วนที่เข้ารหัส 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]
}

ข้อผิดพลาดที่พบบ่อย

ผมพบข้อผิดพลาดทั้งสี่นี้ในการ code review จริง — โดยเฉพาะสองข้อแรกที่ปรากฏขึ้นเกือบทุกครั้ง ที่ใครบางคน integrate auth provider ใหม่

ใช้ StdEncoding กับ input แบบ URL-safe

ปัญหา: JWT token และ OAuth token ใช้ Base64 alphabet แบบ URL-safe (- และ _) การส่งให้ StdEncoding.DecodeString จะล้มเหลวด้วย 'illegal base64 data'

วิธีแก้ไข: ตรวจสอบแหล่งที่มาของ input: token จากระบบ auth ใช้ RawURLEncoding; ไฟล์แนบ binary ใช้ 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 เขียนลง buffer ที่จัดสรรไว้ล่วงหน้าและคืนจำนวน byte ที่เขียนจริง DecodedLen คืนค่าขอบเขตบน ดังนั้น tail ของ buffer อาจมี garbage byte

วิธีแก้ไข: ตัด slice ผลลัพธ์ด้วย 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
ไม่ลบ whitespace ก่อน decode

ปัญหา: String Base64 ที่คัดลอกมาจาก terminal, อีเมล หรือ config file มักมี newline หรือ space ที่ท้าย การส่งตรงไปยัง DecodeString จะล้มเหลวที่อักขระ whitespace

วิธีแก้ไข: เรียก strings.TrimSpace (และ strings.ReplaceAll สำหรับ newline ที่ฝังอยู่) ก่อน decode

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
แปลง decoded byte เป็น string อย่างไม่ถูกต้อง

ปัญหา: การเรียก string(decoded) กับข้อมูล binary (รูปภาพ, compressed payload) ทำให้ได้ UTF-8 string ที่ไม่ถูกต้อง Go string สามารถเก็บ byte ใด ๆ ได้ แต่บางการดำเนินการจะทำให้เนื้อหาเสียหาย

วิธีแก้ไข: เก็บข้อมูล binary เป็น []byte ตลอด pipeline เรียก 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)

การเปรียบเทียบเมธอด

ทุกรูปแบบมาพร้อมกับ standard library — ไม่มี dependency ภายนอกสำหรับสิ่งเหล่านี้

เมธอด
ประเภท Input
รูปแบบการเข้ารหัส
Streaming
Alphabet กำหนดเอง
Padding กำหนดเอง
ต้องติดตั้งเพิ่ม
StdEncoding.DecodeString
string
มาตรฐาน
ไม่ (stdlib)
URLEncoding.DecodeString
string
URL-safe
ไม่ (stdlib)
RawStdEncoding.DecodeString
string
มาตรฐาน (ไม่มี padding)
ไม่ (stdlib)
RawURLEncoding.DecodeString
string
URL-safe (ไม่มี padding)
ไม่ (stdlib)
StdEncoding.Decode
[]byte
มาตรฐาน
ไม่ (stdlib)
base64.NewDecoder
io.Reader
ทุกรูปแบบ
ไม่ (stdlib)
encoding/base64 + NewEncoding
string
Alphabet กำหนดเอง
ไม่ (stdlib)

สำหรับ JWT token และ OAuth flow: RawURLEncoding สำหรับไฟล์แนบอีเมลและ MIME data: StdEncoding สำหรับไฟล์ binary ขนาดใหญ่จากดิสก์หรือเครือข่าย: ครอบ reader ด้วย base64.NewDecoder — ทำให้การใช้หน่วยความจำคงที่ไม่ว่าไฟล์จะมีขนาดเท่าใด ต้องการ alphabet กำหนดเอง? base64.NewEncoding(alphabet) สร้าง encoding object ใหม่สำหรับกรณีใช้งานพิเศษ

สำหรับการตรวจสอบแบบรวดเร็วระหว่างการพัฒนา ตัวถอดรหัส Base64 ออนไลน์ เร็วกว่าการเปิด Go program

คำถามที่พบบ่อย

จะถอดรหัส Base64 ใน Go ได้อย่างไร?

import encoding/base64 แล้วเรียก base64.StdEncoding.DecodeString(s) ฟังก์ชันนี้คืนค่า ([]byte, error) — ต้องตรวจสอบ error เสมอ หากข้อความใช้อักขระ URL-safe (- และ _ แทน + และ /) ให้ใช้ base64.URLEncoding.DecodeString แทน สำหรับ JWT token และ API สมัยใหม่ส่วนใหญ่ RawURLEncoding (ไม่มี padding) คือตัวเลือกที่เหมาะสม

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 มาตรฐานที่มีอักขระ + และ / พร้อม padding = ตามที่กำหนดใน RFC 4648 §4 URLEncoding แทน + ด้วย - และ / ด้วย _ ทำให้ผลลัพธ์ปลอดภัยในการใช้ใน URL และ HTTP header โดยไม่ต้อง percent-encoding ตามที่กำหนดใน RFC 4648 §5 ใช้ URLEncoding สำหรับ JWT token, OAuth token และข้อมูลที่ฝังใน query string

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 ได้อย่างไร?

ข้อผิดพลาดนี้หมายความว่า input มีอักขระที่อยู่นอก alphabet ที่คาดหวัง หรือ padding ไม่ถูกต้อง สาเหตุที่พบบ่อย 3 ประการ: ใช้ StdEncoding กับ input แบบ URL-safe (เปลี่ยนไปใช้ URLEncoding), ใช้ encoder แบบมี padding กับ input ที่ไม่มี padding (เปลี่ยนไปใช้ RawStdEncoding/RawURLEncoding) หรือมี whitespace/newline ที่ท้าย แก้ด้วยการใช้ strings.TrimSpace ก่อน decode

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 แบบ streaming สำหรับไฟล์ขนาดใหญ่ใน Go ได้อย่างไร?

ใช้ base64.NewDecoder(base64.StdEncoding, reader) ซึ่งครอบ io.Reader ใด ๆ และถอดรหัสแบบ on-the-fly จากนั้นส่งผ่าน io.Copy เพื่อเขียนไปยังปลายทางโดยไม่ต้องบัฟเฟอร์ไฟล์ทั้งหมดในหน่วยความจำ นี่คือรูปแบบมาตรฐานสำหรับการถอดรหัสไฟล์แนบแบบ binary ที่เข้ารหัส Base64 หรือ payload ข้อมูลขนาดใหญ่

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

ถอดรหัส JWT payload แบบ Base64 ใน Go โดยไม่ใช้ library JWT ได้หรือไม่?

ได้ JWT คือสามส่วนที่เข้ารหัส Base64url คั่นด้วยจุด แยกด้วย "." แล้วถอดรหัสส่วนที่สอง (index 1) ด้วย base64.RawURLEncoding.DecodeString — header และ payload ของ JWT ใช้ alphabet แบบ URL-safe และไม่มี padding ส่วน signature (index 2) เป็นข้อมูล binary และมักต้องการเฉพาะเพื่อการตรวจสอบความถูกต้องเท่านั้น

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 response?

ตรวจสอบเอกสาร API หรือดูที่ encoded string หากมีอักขระ + หรือ / และลงท้ายด้วย = ให้ใช้ StdEncoding หากใช้อักขระ - และ _ โดยไม่มี = ให้ใช้ RawURLEncoding เมื่อไม่แน่ใจ ลอง RawURLEncoding ก่อน — API สมัยใหม่ส่วนใหญ่ (OAuth2, JWT, Google Cloud, AWS) ใช้ Base64 แบบ URL-safe โดยไม่มี padding

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 — เข้ารหัสข้อมูล binary หรือข้อความเป็น Base64 ในเบราว์เซอร์ มีประโยชน์สำหรับสร้าง test fixture เพื่อวางใน Go unit test
  • ตัวถอดรหัส JWT — แยกและถอดรหัสทั้งสาม JWT segment พร้อมกัน พร้อมการตรวจสอบ payload ทีละ field — ไม่ต้องใช้โค้ด Go เมื่อต้องการอ่าน token ระหว่างการ debug
  • ตัวถอดรหัส URL — ถอดรหัส URL-encoded string แบบ percent-decode มีประโยชน์เมื่อ API response ผสม Base64url data กับ query parameter แบบ percent-encoded
  • ตัวจัดรูปแบบ JSON — หลังจากถอดรหัส JWT payload หรือ API response แบบ Base64 วาง JSON ที่นี่เพื่อ pretty-print และตรวจสอบโครงสร้างทันที
มีให้ในภาษาอื่นด้วย: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.