Belajar Chi - Setup & Hello World
Episode 3 of 23

Belajar Chi - Setup & Hello World

Episode ini membangun project chi pertama yang berjalan: membuat router dengan chi.NewRouter, mendaftarkan handler pertama, dan menjalankan server dengan http.ListenAndServe. Kalian juga belajar struktur Handler dan ServeHTTP, serta mengembalikan respons JSON secara manual.

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

Pendahuluan

Cukup teori. Episode 3 mengajak kalian membangun project chi pertama yang benar-benar berjalan: hello world. Ini momen paling penting dalam sebuah series — ketika kalian melihat route pertama hidup dan merespons request lewat curl, semua konsep di episode 1 dan 2 mulai terasa nyata.

Target episode ini: membuat server kecil dengan dua endpoint, memahami apa itu http.Handler dan ServeHTTP, serta mengembalikan JSON secara manual tanpa bantuan library tambahan. Semua pola ini akan menjadi fondasi seluruh episode berikutnya.

Proyek Awal

Menyiapkan Module dan Dependency

Pastikan environment episode 0 sudah siap. Buat module dan install chi v5:

Setup project
mkdir hello-chi
cd hello-chi
go mod init github.com/username/hello-chi
go get github.com/go-chi/chi/v5@latest

go get github.com/go-chi/chi/v5@latest menambahkan dependency ke go.mod. Setelah itu, buat file main.go — seluruh aplikasi hello world kita hidup di satu file ini.

Router Pertama

Hello world dengan chi
package main
 
import (
    "net/http"
 
    "github.com/go-chi/chi/v5"
)
 
func main() {
    r := chi.NewRouter()
    r.Get("/", func(w http.ResponseWriter, req *http.Request) {
        w.Write([]byte("Halo Dunia"))
    })
 
    http.ListenAndServe(":8080", r)
}

chi.NewRouter() membuat router kosong, lalu r.Get("/", handler) mendaftarkan handler untuk method GET pada path root. Handler ditulis sebagai closure yang menerima http.ResponseWriter dan *http.Request — bentuk yang sama persis dengan http.HandlerFunc.

Menjalankan dan Menguji Server

Jalankan server, lalu test dengan curl dari terminal lain:

Jalankan server
go run main.go
Test dengan curl
curl -i http://localhost:8080/

Respons yang diharapkan: status 200 OK, header dari http.Server, dan body Halo Dunia. curl -i http://localhost:8080/ menampilkan header sekaligus body sehingga kalian bisa melihat keseluruhan respons.

Tip

Karena r adalah http.Handler, kalian juga bisa menjalankannya dengan http.ListenAndServe di goroutine dan menangani shutdown — kita akan membahasnya di episode 10.

Handler dan ServeHTTP

Interface Dua Method

Sebenarnya sebuah handler cukup mengimplementasikan satu method:

Interface http.Handler
type Handler interface {
    ServeHTTP(w http.ResponseWriter, req *http.Request)
}

Saat kita menulis func(w http.ResponseWriter, req *http.Request), Go otomatis mengubahnya menjadi http.HandlerFunc yang mengimplementasikan interface tersebut. Di sinilah letak keindahan chi: tidak ada tipe handler khusus. Handler chi adalah handler net/http.

Untuk project nyata, handler sebaiknya bukan closure anonim di dalam main:

Handler sebagai fungsi
func helloHandler(w http.ResponseWriter, req *http.Request) {
    w.Write([]byte("Halo Dunia"))
}
 
func main() {
    r := chi.NewRouter()
    r.Get("/", helloHandler)
    http.ListenAndServe(":8080", r)
}

Pola r.Get("/", helloHandler) memakai fungsi bertipe http.HandlerFunc, yang otomatis dipakai chi tanpa konversi manual.

Respons JSON Manual

Header, Status, dan Body

REST API hampir selalu mengembalikan JSON. Manual encoding cukup sederhana:

Respons JSON manual
func healthHandler(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    json.NewEncoder(w).Encode(map[string]string{
        "status": "ok",
    })
}

Urutannya penting: set header dulu, tulis status, baru encode body. json.NewEncoder(w).Encode(...) menulis JSON langsung ke ResponseWriter dengan escaping yang benar.

Melayani Lebih dari Satu Route

Tambahkan endpoint kesehatan ke router:

Dua endpoint
func main() {
    r := chi.NewRouter()
    r.Get("/", helloHandler)
    r.Get("/health", healthHandler)
    http.ListenAndServe(":8080", r)
}

Sekarang test kedua endpoint:

Test endpoint kesehatan
curl -i http://localhost:8080/health

curl -i http://localhost:8080/health harus mengembalikan status 200 OK dengan header Content-Type: application/json dan body {"status":"ok"}.

Prinsip: chi Hanyalah net/http

Tidak Ada yang Ajaib

Setiap handler di chi bisa dipindahkan ke http.ServeMux atau http.ListenAndServe tanpa perubahan. Demikian juga sebaliknya: handler net/http apa pun bisa didaftarkan ke chi. Prinsip inilah yang membuat chi kompatibel dengan seluruh ekosistem.

Untuk membuktikannya, ganti router dengan http.ServeMux:

Bukti chi is net/http
func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", helloHandler)
    http.ListenAndServe(":8080", mux)
}

Handler helloHandler berjalan mulus tanpa menyentuh satu baris pun. http.NewServeMux() inilah yang dibungkus chi dengan tambahan params, subrouter, dan middleware — topik kita mulai episode 4.

Penutup

Inti yang harus dibawa pulang:

  • Setup project: go mod init lalu go get github.com/go-chi/chi/v5@latest.
  • chi.NewRouter() lalu r.Get("/", handler) adalah resep dasar.
  • Handler chi adalah http.Handler biasa; tidak ada tipe khusus.
  • Respons JSON manual: set header, tulis status, encode body.
  • Server dijalankan dengan http.ListenAndServe(":8080", r).
  • chi tidak meng-invent ulang net/http — handler bisa bolak-balik tanpa modifikasi.

Di episode 4 selanjutnya kita masuk ke jantung router: routing, params, dan patterns — method routing, path param {id}, wildcard {path:*}, regex {id:[0-9]+}, sampai NotFound dan MethodNotAllowed. Ini akan mengubah cara kalian memandang URL.