unisbadri.com » Python Java Golang Typescript Kotlin Ruby Rust Dart PHP
Yaml

Yaml #

YAML (YAML Ain’t Markup Language) adalah format serialisasi data yang dirancang agar mudah dibaca manusia (human-readable). YAML sangat populer untuk:

  • File konfigurasi aplikasi
  • DevOps (Docker Compose, Kubernetes, GitHub Actions)
  • Infrastructure as Code
  • CI/CD pipeline
  • Configuration-driven systems

Dalam ekosistem Golang, YAML sering digunakan untuk:

  • Konfigurasi aplikasi production
  • Environment management
  • Feature flags
  • Mapping config ke struct strongly-typed

Artikel ini membahas secara mendalam:

  1. Konsep dasar YAML
  2. Library YAML di Go
  3. Encoding & Decoding
  4. Struct tags dan advanced mapping
  5. Custom marshal & unmarshal
  6. Strict mode & validation
  7. Multi-document YAML
  8. Anchor, alias, dan merge key
  9. Dynamic config handling
  10. Performance consideration
  11. Best practice production

Mengenal YAML #

Contoh YAML:

server:
  host: localhost
  port: 8080

database:
  driver: postgres
  host: db
  port: 5432
  ssl: false

Karakteristik utama:

  • Indentation-based (spasi, bukan tab)
  • Mendukung nested object
  • Mendukung list
  • Mendukung komentar (#)
  • Mendukung multiple document

Library YAML di Golang #

Library paling umum digunakan:

gopkg.in/yaml.v3

Install:

go get gopkg.in/yaml.v3

Kenapa v3?

  • Mendukung Node API
  • Support strict decoding
  • Lebih stabil untuk production

Basic Decoding (Unmarshal) #

import "gopkg.in/yaml.v3"

type Config struct {
    Server struct {
        Host string `yaml:"host"`
        Port int    `yaml:"port"`
    } `yaml:"server"`
}

var cfg Config
err := yaml.Unmarshal(data, &cfg)

⚠ Harus pointer.


Basic Encoding (Marshal) #

b, err := yaml.Marshal(cfg)

YAML akan di-generate otomatis berdasarkan struct.


Struct Tag YAML #

Contoh:

type Database struct {
    Driver string `yaml:"driver"`
    Host   string `yaml:"host"`
    Port   int    `yaml:"port"`
    SSL    bool   `yaml:"ssl,omitempty"`
}

Opsi penting:

  • omitempty
  • - (ignore field)

Berbeda dengan JSON: YAML tidak case-sensitive secara default, tetapi tetap disarankan eksplisit menggunakan tag.


Strict Mode (UnmarshalStrict) #

Secara default, unknown field diabaikan.

Untuk strict mode:

decoder := yaml.NewDecoder(reader)
decoder.KnownFields(true)
err := decoder.Decode(&cfg)

Ini penting agar:

  • Salah ketik config terdeteksi
  • Tidak ada silent failure

Best practice: aktifkan KnownFields(true) untuk production.


Multi Document YAML #

YAML mendukung multiple document:

---
app: service-a
---
app: service-b

Handling di Go:

decoder := yaml.NewDecoder(file)
for {
    var doc map[string]interface{}
    err := decoder.Decode(&doc)
    if err == io.EOF {
        break
    }
}

Digunakan di Kubernetes manifest.


YAML Anchor & Alias #

Contoh:

default: &default
  timeout: 30
  retries: 3

serviceA:
  <<: *default
  url: http://a

YAML v3 akan resolve merge key secara otomatis saat Unmarshal.

Namun hati-hati:

  • Tidak semua library support penuh
  • Debug bisa membingungkan

Handling Nested & Slice #

servers:
  - host: a
    port: 8080
  - host: b
    port: 8081

Struct:

type Server struct {
    Host string `yaml:"host"`
    Port int    `yaml:"port"`
}

type Config struct {
    Servers []Server `yaml:"servers"`
}

Zero Value vs Missing Field #

Masalah umum pada config update.

Solusi: gunakan pointer.

type Config struct {
    Timeout *int `yaml:"timeout"`
}

Jika nil → tidak diset Jika non-nil → override


Custom Unmarshal #

Untuk validasi atau transformasi.

func (c *Config) UnmarshalYAML(value *yaml.Node) error {
    type rawConfig Config
    var aux rawConfig

    if err := value.Decode(&aux); err != nil {
        return err
    }

    if aux.Server.Port <= 0 {
        return fmt.Errorf("invalid port")
    }

    *c = Config(aux)
    return nil
}

Digunakan untuk:

  • Validasi
  • Default value injection
  • Transformasi format

Default Value Pattern #

YAML tidak punya default value.

Pattern umum:

cfg := Config{
    Server: Server{
        Port: 8080,
    },
}

yaml.Unmarshal(data, &cfg)

Nilai yang tidak ada akan tetap default.


Dynamic YAML (map[string]interface{}) #

var data map[string]interface{}
yaml.Unmarshal(b, &data)

Masalah:

  • Type assertion kompleks
  • Tidak type-safe
  • Sulit maintain

Gunakan hanya jika schema benar-benar dinamis.


YAML vs JSON dalam Config #

Kenapa YAML populer untuk config?

  • Lebih readable
  • Mendukung komentar
  • Indentation natural

Kenapa JSON kadang lebih aman?

  • Tidak ambigu
  • Parser lebih ketat
  • Lebih cepat

Tradeoff:

YAML lebih fleksibel tapi lebih kompleks.


Security Concern #

Beberapa risiko:

  • Large file DOS
  • Resource exhaustion
  • Unexpected type coercion

Mitigasi:

  • Batasi ukuran file
  • Gunakan strict mode
  • Validasi setelah decode

Performance Consideration #

YAML parsing lebih lambat dari JSON karena:

  • Lebih kompleks grammar
  • Indentation parsing
  • Support anchor & merge

Untuk high-throughput system:

  • Hindari parsing YAML per request
  • Parse sekali saat startup
  • Simpan di memory

Production Config Pattern #

Best practice umum:

  1. Load YAML saat startup
  2. Inject default value
  3. Validate config
  4. Freeze config (read-only)
  5. Jangan reload tanpa kontrol

Contoh pattern:

Load → Merge Env → Validate → Start App

Sering digabung dengan:

  • ENV override
  • Secret manager
  • CLI flag

Integrasi dengan ENV #

Pattern umum:

  1. Load YAML
  2. Override dengan environment variable

Contoh:

APP_SERVER_PORT=9090

Mapping manual atau menggunakan library tambahan.


Common Mistakes #

  1. Menggunakan tab (harus spasi)
  2. Tidak strict mode
  3. Tidak validasi setelah decode
  4. Menaruh logic kompleks di config
  5. Reload config tanpa concurrency safety
  6. Menggunakan dynamic map berlebihan

Penutup #

YAML di Golang sangat powerful untuk configuration-driven system, namun memiliki kompleksitas lebih tinggi dibanding JSON.

Menguasai YAML handling berarti memahami:

  • Mapping struct
  • Strict decoding
  • Default injection
  • Custom unmarshal
  • Multi-document
  • Anchor & merge
  • Security consideration

Untuk production-grade system:

Gunakan YAML sebagai configuration layer, bukan data transport layer.

Parse sekali saat startup, validasi ketat, dan jangan biarkan konfigurasi menjadi sumber bug tersembunyi.

« JSON
About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact