BAB 40: Encoding Base64
Pelajari cara encode dan decode data menggunakan package encoding/base64 di Go, termasuk StdEncoding, URLEncoding, dan penanganan error.
Di bab sebelumnya kita bekerja dengan ekspresi reguler untuk mengenali pola dalam teks. Hasil akhirnya selalu berupa string yang masih bisa dibaca — kata yang diekstrak, tanggal yang diparsing, teks yang diganti. Namun ada kelas masalah yang berbeda: bagaimana mengirim data yang tidak sepenuhnya berupa teks, seperti gambar, file PDF, atau token otentikasi, melalui saluran komunikasi yang hanya paham teks?
Base64 adalah jawaban yang paling umum untuk masalah ini. Ia mengkodekan data biner apa pun menjadi karakter ASCII yang aman untuk disisipkan di JSON, HTTP header, atau URL. Go menyediakan package encoding/base64 yang menangani ini dengan dua pendekatan berbeda sesuai kebutuhan.
Encode dan Decode dengan String
Cara termudah menggunakan Base64 di Go adalah lewat StdEncoding.EncodeToString() dan StdEncoding.DecodeString(). Keduanya bekerja langsung dengan string sebagai input dan output.
// dokumen.go
package main
import (
"encoding/base64"
"fmt"
)
func main() {
konten := "Laporan Q1 2026: pendapatan naik 12%, biaya turun 5%"
// encode string ke Base64
terenkripsi := base64.StdEncoding.EncodeToString([]byte(konten))
fmt.Println("encoded:", terenkripsi)
// decode kembali ke string asli
hasilByte, err := base64.StdEncoding.DecodeString(terenkripsi)
if err != nil {
fmt.Println("gagal decode:", err)
return
}
fmt.Println("decoded:", string(hasilByte))
}
encoded: TGFwb3JhbiBRMSAyMDI2OiBwZW5kYXBhdGFuIG5haWsgMTIlLCBiaWF5YSB0dXJ1biA1JQ==
decoded: Laporan Q1 2026: pendapatan naik 12%, biaya turun 5%
Perhatikan dua konversi tipe yang terjadi: []byte(konten) mengubah string ke byte slice sebelum di-encode, dan string(hasilByte) mengubah hasil decode kembali ke string. Go tidak bisa langsung meng-encode string — semua input harus berupa []byte.
StdEncoding menggunakan alphabet Base64 standar (huruf, angka, +, /) dan padding = di akhir. Hasil encoding selalu kelipatan 4 karakter, itulah mengapa kamu sering melihat satu atau dua karakter = di akhir string Base64.
Encode dan Decode dengan Byte Slice
Selain EncodeToString, ada pasangan fungsi Encode() dan Decode() yang bekerja sepenuhnya dengan []byte. Pendekatan ini lebih verbose tapi berguna ketika kamu bekerja langsung dengan data biner — misalnya isi file yang dibaca dari disk.
// dokumen.go
package main
import (
"encoding/base64"
"fmt"
)
func main() {
sumber := []byte("token-akses:rahasia-ganti-ini-di-produksi")
// siapkan slice dengan ukuran yang tepat
ukuranEncode := base64.StdEncoding.EncodedLen(len(sumber))
hasil := make([]byte, ukuranEncode)
base64.StdEncoding.Encode(hasil, sumber)
fmt.Println("encoded:", string(hasil))
// decode kembali
ukuranDecode := base64.StdEncoding.DecodedLen(len(hasil))
asli := make([]byte, ukuranDecode)
n, err := base64.StdEncoding.Decode(asli, hasil)
if err != nil {
fmt.Println("gagal decode:", err)
return
}
// n adalah jumlah byte yang benar-benar ditulis (tanpa padding)
fmt.Println("decoded:", string(asli[:n]))
}
encoded: dG9rZW4tYWtzZXM6cmFoYXNpYS1nYW50aS1pbmktZGktcHJvZHVrc2k=
decoded: token-akses:rahasia-ganti-ini-di-produksi
EncodedLen() dan DecodedLen() menghitung berapa byte yang dibutuhkan untuk hasil encoding/decoding, sehingga kamu bisa mengalokasikan slice dengan ukuran yang tepat. Nilai n yang dikembalikan Decode() penting diperhatikan — DecodedLen() kadang mengestimasi lebih besar dari aktual karena memperhitungkan padding.
Untuk sebagian besar kebutuhan sehari-hari, EncodeToString dan DecodeString jauh lebih ringkas. Gunakan Encode/Decode hanya saat kamu memang bekerja dengan []byte di seluruh pipeline dan ingin menghindari konversi ke string.
Encoding Khusus URL
StdEncoding menggunakan karakter + dan / yang punya makna khusus dalam URL. Jika hasil Base64 akan disisipkan ke URL — misalnya sebagai query parameter atau path segment — gunakan URLEncoding sebagai gantinya.
// dokumen.go
package main
import (
"encoding/base64"
"fmt"
)
func main() {
alamat := "https://api.internal/laporan?filter=divisi:OPS&tahun=2026"
// StdEncoding: mengandung + dan / yang tidak aman untuk URL
stdResult := base64.StdEncoding.EncodeToString([]byte(alamat))
fmt.Println("StdEncoding:", stdResult)
// URLEncoding: + diganti -, / diganti _
urlResult := base64.URLEncoding.EncodeToString([]byte(alamat))
fmt.Println("URLEncoding:", urlResult)
// decode kembali dengan URLEncoding
decoded, err := base64.URLEncoding.DecodeString(urlResult)
if err != nil {
fmt.Println("gagal decode:", err)
return
}
fmt.Println("decoded:", string(decoded))
}
StdEncoding: aHR0cHM6Ly9hcGkuaW50ZXJuYWwvbGFwb3Jhbj9maWx0ZXI9ZGl2aXNpOk9QUyZ0YWh1bj0yMDI2
URLEncoding: aHR0cHM6Ly9hcGkuaW50ZXJuYWwvbGFwb3Jhbj9maWx0ZXI9ZGl2aXNpOk9QUyZ0YWh1bj0yMDI2
decoded: https://api.internal/laporan?filter=divisi:OPS&tahun=2026
Dalam contoh ini kedua output terlihat sama karena string sumber kebetulan tidak menghasilkan + atau /. Perbedaannya baru terlihat saat data yang di-encode mengandung byte yang memetakan ke karakter tersebut. Prinsipnya sederhana: jika Base64 akan masuk ke URL, selalu pakai URLEncoding.
Perbandingan StdEncoding vs URLEncoding
Kedua encoding menggunakan alphabet yang hampir sama, hanya berbeda di dua karakter:
| Karakter | StdEncoding | URLEncoding |
|---|---|---|
| Index 62 | + | - |
| Index 63 | / | _ |
| Padding | = | = |
Keduanya menghasilkan output yang panjangnya sama dan bisa menampung data yang sama. Pilih berdasarkan konteks penggunaan: StdEncoding untuk encoding umum, URLEncoding untuk URL dan cookie.
Studi Kasus: Token Akses Sederhana
Menggabungkan Base64 dengan string formatting untuk membuat mekanisme token sederhana yang biasa dipakai sebagai HTTP Basic Auth.
// dokumen.go
package main
import (
"encoding/base64"
"fmt"
"strings"
)
// buatToken membuat Basic Auth token dari ID pengguna dan kunci rahasia
func buatToken(idPengguna, kunci string) string {
kredensial := fmt.Sprintf("%s:%s", idPengguna, kunci)
return base64.StdEncoding.EncodeToString([]byte(kredensial))
}
// parseToken mengurai token Basic Auth menjadi komponen-komponennya
func parseToken(token string) (idPengguna, kunci string, err error) {
decoded, decErr := base64.StdEncoding.DecodeString(token)
if decErr != nil {
return "", "", fmt.Errorf("token tidak valid: %w", decErr)
}
bagian := strings.SplitN(string(decoded), ":", 2)
if len(bagian) != 2 {
return "", "", fmt.Errorf("format token salah")
}
return bagian[0], bagian[1], nil
}
func main() {
// buat token untuk beberapa akun
akun := []struct{ id, kunci string }{
{"ops-admin", "kunci-ops-2026"},
{"fin-viewer", "baca-saja-fin"},
{"it-deployer", "deploy-prod-key"},
}
for _, a := range akun {
token := buatToken(a.id, a.kunci)
fmt.Printf("%-12s => %s\n", a.id, token)
// verifikasi dengan parse ulang
id, _, err := parseToken(token)
if err != nil {
fmt.Println("error:", err)
continue
}
fmt.Printf("%-12s verified: %s\n", "", id)
}
}
ops-admin => b3BzLWFkbWluOmt1bmNpLW9wcy0yMDI2
verified: ops-admin
fin-viewer => ZmluLXZpZXdlcjpiYWNhLXNhamEtZmlu
verified: fin-viewer
it-deployer => aXQtZGVwbG95ZXI6ZGVwbG95LXByb2Qta2V5
verified: it-deployer
Base64 bukan enkripsi. Data yang di-encode Base64 bisa dengan mudah di-decode oleh siapa pun. Jangan gunakan Base64 untuk menyembunyikan informasi sensitif seperti password atau kunci API. Gunakan hanya untuk transport dan representasi data, bukan untuk keamanan.
Latihan
Latihan 1 — Encode file simulasi:
Buat fungsi enkodeKonten(isi string) string yang menerima isi dokumen teks dan mengembalikan representasi Base64-nya. Kemudian buat fungsi kebalikannya dekodeKonten(encoded string) (string, error). Uji dengan teks yang mengandung karakter khusus seperti &, <, >, dan karakter Unicode.
Latihan 2 — Validasi token:
Kembangkan fungsi parseToken dari studi kasus di atas agar mengembalikan error jika ID pengguna kosong atau kunci lebih pendek dari 8 karakter. Tambahkan juga fungsi validasiToken(token, idDiharapkan string) bool yang mengembalikan true hanya jika token valid dan ID-nya cocok.
Latihan 3 — URL-safe encoding:
Buat fungsi buatURLToken(payload string) string yang meng-encode payload menggunakan URLEncoding tanpa padding (base64.RawURLEncoding) agar hasilnya bisa langsung disisipkan ke URL tanpa escaping. Bandingkan panjang outputnya dengan StdEncoding.
Base64 adalah salah satu building block yang sering muncul di balik layar: di JWT, di HTTP Basic Auth, di attachment email, di data URI gambar. Sekarang kamu tahu cara menggunakannya secara langsung di Go. Ada satu hal penting yang perlu diingat dari bab ini: Base64 bisa di-decode oleh siapa pun. Ia bukan mekanisme keamanan — ia hanya representasi. Lalu bagaimana caranya menyimpan data yang benar-benar tidak bisa dikembalikan ke bentuk aslinya, seperti password? Jawabannya ada di hashing, dan itulah yang akan kita bahas selanjutnya.