Go io/fs dan Embed
Definisi
io/fs adalah abstraction atas sistem berkas di Go: menyediakan interface fs.FS yang dipakai untuk membaca file secara uniform, baik dari disk, memory, maupun embed. embed memungkinkan menyematkan file (template, aset statis, SQL) langsung ke dalam binary pada saat compile.
Kapan dipakai
- embed: butuh aset ikut binary tanpa mengandalkan file external (CLI tool, web server tanpa folder
static/, template HTML). - fs.FS: ingin membaca banyak sumber secara seragam, atau menulis test dengan
fstest.MapFStanpa menyentuh disk. - Jangan embed file yang harus bisa diubah saat runtime (konfigurasi dinamis) — embed bersifat read-only sejak compile.
Cara kerja
embed.FS
import "embed"
//go:embed templates/*.html
var templatesFS embed.FS
func render(name string) (string, error) {
b, err := templatesFS.ReadFile("templates/index.html")
if err != nil {
return "", err
}
return string(b), nil
}- Direktif
//go:embedharus tepat di atas variabel bertipeembed.FS(atau[]byte/stringuntuk satu file). - Path relatif terhadap file Go yang memuat direktif.
fs.FS sebagai abstraction
func loadConfig(fsys fs.FS, name string) ([]byte, error) {
return fs.ReadFile(fsys, name)
}Fungsi di atas bisa menerima os.DirFS("configs"), embed.FS, atau fstest.MapFS di test.
Struktur alur
Loading diagram...
Contoh test tanpa disk
func TestLoadConfig(t *testing.T) {
fsys := fstest.MapFS{
"app.yaml": &fstest.MapFile{Data: []byte("debug: true")},
}
data, err := loadConfig(fsys, "app.yaml")
if err != nil {
t.Fatal(err)
}
if !bytes.Contains(data, []byte("debug")) {
t.Fatal("konten salah")
}
}Catatan implementasi
embed.FStidak bisa di-write; untuk aset yang berubah runtime, simpan di disk/volume eksternal.- Gunakan
fs.WalkDiruntuk iterasi isifs.FSsecara rekursif. os.DirFSmembatasi akses ke dalam direktori tersebut (aman untuk batasi path traversal).
Kesalahan umum
- Path salah: lupa bahwa path di
ReadFileharus sama persis dengan pola embed (termasuk prefix folder). - Edit file embed tapi binary tidak di-rebuild: perubahan file sumber tidak otomatis masuk binary lama.
- Embed file terlalu besar: membesarkan ukuran binary tanpa perlu.
- Mencampur baca/write:
embed.FSread-only; jangan asumsikan bisaWriteFile.