Belajar Gin - Fitur Stabil Terbaru (v1.11 & v1.12)
Series/Belajar Gin/Episode 20
Episode 20 of 23

Belajar Gin - Fitur Stabil Terbaru (v1.11 & v1.12)

Episode ini meninjau fitur stabil terbaru Gin: v1.11 dengan ShouldBindBodyWithPlain, HTTP/3 eksperimental, dan pembersihan deprecated; v1.12 dengan encoding.UnmarshalText, Protobuf, OptionFunc, serta kemudahan yang dibawa engine.With.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Sejak episode 0 kita memakai Gin v1.12.0, tetapi belum pernah meninjau apa saja yang berubah di dua rilis terakhir. Episode 20 ini membedah fitur stabil terbaru Gin: rilis v1.11.0 (September 2025) dan v1.12.0 (Februari 2026). Kalian akan melihat bagaimana binding diperkuat, apa saja yang dibersihkan dari API lama, dan fitur mana yang paling berguna untuk project kalian.

Memahami arah rilis penting karena memengaruhi keputusan upgrade. Kabar baiknya: tidak ada breaking change besar — upgrade v1.10 ke v1.12 umumnya cukup go get. Yang berubah adalah tambahan API yang membuat kode lebih ekspresif dan lebih cepat.

Perjalanan dari Gin v1.11

Fitur Binding Baru

Gin v1.11 memperkenalkan BindPlain dan ShouldBindBodyWithPlain untuk membaca body teks mentah, plus dukungan unixMilli dan unixMicro pada binding waktu:

Bind body teks mentah
type Message struct {
    Content string
}
 
func webhookHandler(c *gin.Context) {
    var msg Message
    if err := c.ShouldBindBodyWithPlain(&msg, binding.String); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, gin.H{"content": msg.Content})
}

c.ShouldBindBodyWithPlain(&msg, binding.String) memetakan body plain text ke field string. Ini berguna untuk webhook yang mengirim payload teks tanpa Content-Type: application/json. Versi ini juga menandai fungsi deprecated lama untuk dirapikan, dan menambah RunQUIC untuk HTTP/3 yang masih eksperimental.

encoding.UnmarshalText untuk Binding

Tipe Kustom di URI dan Query

Fitur unggulan v1.12: binding uri dan query kini menghormati encoding.UnmarshalText. Artinya kalian bisa membuat tipe kustom yang mengurai nilainya sendiri:

Tipe kustom dengan UnmarshalText
type Clock struct {
    time.Time
}
 
func (c *Clock) UnmarshalText(text []byte) error {
    t, err := time.Parse("15:04:05", string(text))
    if err != nil {
        return err
    }
    c.Time = t
    return nil
}
 
type ScheduleRequest struct {
    Start Clock `form:"start" binding:"required"`
}
Gunakan di query binding
var req ScheduleRequest
if err := c.ShouldBindQuery(&req); err != nil {
    c.JSON(400, gin.H{"error": err.Error()})
    return
}

c.ShouldBindQuery(&req) memanggil UnmarshalText pada tipe Clock saat mengisi query start=08:30:00. Sebelum v1.12, penguraian format khusus di query harus dilakukan manual setelah binding. Sekarang kustomisasi disimpan di tipe itu sendiri, sehingga aturan berlaku konsisten di semua route.

Binding TOML, YAML, dan XML

ShouldBindBodyWith yang Lebih Luas

Rangkaian ShouldBindBodyWith* kini melayani lebih banyak format:

Pilih format body
c.ShouldBindBodyWithJSON(&data)
c.ShouldBindBodyWithXML(&data)
c.ShouldBindBodyWithYAML(&data)
c.ShouldBindBodyWithTOML(&data)

c.ShouldBindBodyWithYAML(&data) membaca body YAML sambil menyimpan salinan body di context — sehingga bisa dipanggil lebih dari sekali dalam satu handler, berbeda dari ShouldBind biasa. Di v1.12, penanganan body untuk TOML dan YAML juga dibenahi agar tidak mendekode ganda, dan bind body untuk Protobuf ikut didukung dalam content negotiation.

OptionFunc dan engine.With

Konfigurasi dengan Functional Options

Sejak v1.10, gin.New dan gin.Default menerima OptionFunc — fungsi yang memodifikasi engine:

OptionFunc kustom
func withLogger(logger *slog.Logger) gin.OptionFunc {
    return func(e *gin.Engine) {
        e.Use(slogMiddleware(logger))
    }
}
 
r := gin.New(withLogger(appLogger))

gin.New(withLogger(appLogger)) mengonfigurasi engine di saat konstruksi, bukan setelahnya. Fungsi withLogger mengembalikan OptionFunc yang memasang middleware. Pendekatan ini membuat komposisi konfigurasi menjadi modular dan mudah diuji.

Berantai dengan engine.With

Untuk menerapkan opsi setelah engine ada, gunakan engine.With:

engine.With berantai
r := gin.New()
r.With(withLogger(appLogger), withRecovery(appLogger))

engine.With(withLogger(...)) mengembalikan engine yang sudah dikonfigurasi, sehingga bisa dirantai. Pola functional options ini semakin rapi di v1.11 dan v1.12 — kalian bisa merangkai logger, recovery, dan middleware lain dalam satu baris ekspresif.

Logger dan Skipper

Melewati Endpoint Tertentu

Gin kini memiliki tipe Skipper — fungsi yang menerima context dan mengembalikan boolean — untuk memutuskan apakah middleware dijalankan:

Skipper untuk logger
type Skipper func(c *gin.Context) bool
 
skipHealth := func(c *gin.Context) bool {
    return c.Request.URL.Path == "/healthz"
}
 
r.Use(loggerMiddlewareWith(skipHealth))

skipHealth membuat endpoint health dan metrics tidak membanjiri log akses — pola yang langsung berguna setelah episode 18. Di v1.12, konfigurasi logger juga memungkinkan menonaktifkan output query string dan mewarnai latensi agar request lambat mudah dikenali di terminal.

Upgrade yang Lancar

Untuk meng-upgrade project yang sudah ada:

Upgrade ke v1.12
go get github.com/gin-gonic/gin@v1.12.0
go mod tidy
go build ./...

go get github.com/gin-gonic/gin@v1.12.0 menarik rilis terbaru. Karena tidak ada breaking change pada API publik yang kalian pakai, go build ./... seharusnya sukses langsung. Perhatikan bahwa v1.12 menetapkan minimum Go 1.25 — pastikan toolchain kalian memenuhi syarat sebelum upgrade.

Penutup

Inti yang harus dibawa pulang:

  • v1.11 menambah ShouldBindBodyWithPlain dan dukungan waktu unixMilli/unixMicro.
  • v1.12 mendukung encoding.UnmarshalText untuk binding uri dan query.
  • ShouldBindBodyWith* kini melayani JSON, XML, YAML, dan TOML secara konsisten.
  • OptionFunc dan engine.With membuat konfigurasi engine menjadi modular.
  • Skipper memungkinkan middleware melewati endpoint tertentu.
  • Upgrade aman karena tidak ada breaking change, dengan syarat Go 1.25+.

Di episode 21 selanjutnya kita akan membedah production-ready architecture — menggabungkan semua pelajaran menjadi arsitektur production: layout modular, graceful shutdown, konfigurasi env, logging terpusat, containerization dengan Docker multi-stage, pipeline CI/CD, dan deployment zero-downtime.

Belajar Gin - Fitur Stabil Terbaru (v1.11 & v1.12) | Belajar Gin