Episode ini membuka komunikasi realtime: WebSocket dengan gorilla/websocket di dalam handler Echo, Server-Sent Events untuk notifikasi satu arah, streaming response untuk data besar, serta use case chat, notifikasi, dan long-lived connections.

Sebagian besar API bekerja satu arah: klien bertanya, server menjawab. Tapi ada dunia di mana server harus mendorong data kapan saja — chat, notifikasi, live price. Episode ini membuka komunikasi realtime di Echo dengan WebSocket dan Server-Sent Events.
Episode 16 ini membahas WebSocket dengan gorilla/websocket, Server-Sent Events untuk notifikasi satu arah, streaming response untuk data besar, serta use case chat dan long-lived connections.
Echo tidak membawa WebSocket bawaan, tapi integrasinya mulus dengan gorilla/websocket. Handler melakukan upgrade dari HTTP biasa:
go get github.com/gorilla/websocketvar upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
e.GET("/ws", func(c echo.Context) error {
ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
if err != nil {
return err
}
defer ws.Close()
for {
msgType, msg, err := ws.ReadMessage()
if err != nil {
return err
}
if err := ws.WriteMessage(msgType, []byte("echo: "+string(msg))); err != nil {
return err
}
}
})Handler ini melakukan echo setiap pesan yang diterima klien. CheckOrigin menentukan asal yang boleh membuka koneksi — di production, validasi origin daripada mengembalikan true selalu.
Jangan pernah menerima semua origin di production. Batasi ke domain aplikasi:
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return r.Host == "app.example.com"
},
}SSE adalah cara sederhana server mengirim update ke klien tanpa memerlukan koneksi dua arah. Klien cukup membuka koneksi HTTP biasa:
e.GET("/events", func(c echo.Context) error {
h := c.Response().Header()
h.Set(echo.HeaderContentType, "text/event-stream")
h.Set(echo.HeaderCacheControl, "no-cache")
h.Set(echo.HeaderConnection, "keep-alive")
for i := 1; i <= 10; i++ {
event := "event: notifikasi\n"
event += "data: pesan ke-" + strconv.Itoa(i) + "\n\n"
if _, err := c.Response().Write([]byte(event)); err != nil {
return err
}
c.Response().Flush()
time.Sleep(time.Second)
}
return nil
})Pola SSE: tulis event dengan format data: <pesan> lalu panggil Flush agar data sampai ke klien segera. Format event harus diakhiri dua newline.
Kombinasikan dengan episode 7: c.Stream dan c.Response().Flush memungkinkan data besar dikirim bertahap. SSE hanyalah satu bentuk streaming; bentuk lain termasuk progress reporting dan pengiriman file besar:
e.GET("/stream", func(c echo.Context) error {
c.Response().Header().Set(echo.HeaderContentType, "text/plain")
for i := 1; i <= 100; i++ {
if _, err := c.Response().Write([]byte("baris " + strconv.Itoa(i) + "\n")); err != nil {
return err
}
c.Response().Flush()
}
return nil
})Klien melihat baris pertama jauh sebelum server selesai menulis baris terakhir — tanpa streaming, seluruh respons harus menunggu selesai.
WebSocket unggul saat komunikasi dua arah dan latensi rendah adalah prioritas: chat, kolaborasi, game. Kelemahannya: koneksi dipegang terus, jadi setiap koneksi mengonsumsi resource dan perlu skala vertikal atau banyak instance dengan mechanisme broadcast terpusat.
SSE unggul untuk notifikasi satu arah — harga, alert, feed — karena lebih sederhana, memakai HTTP biasa yang melewati proxy dan load balancer dengan mudah.
type Hub struct {
clients map[*websocket.Conn]bool
mu sync.Mutex
}
func (h *Hub) broadcast(msg []byte) {
h.mu.Lock()
defer h.mu.Unlock()
for client := range h.clients {
client.WriteMessage(websocket.TextMessage, msg)
}
}Hub dengan mutex melacak semua koneksi aktif dan menyebarkan pesan ke seluruhnya. Ini adalah bentuk sederhana dari pola publish-subscribe.
Episode 16 membuka komunikasi realtime: WebSocket dengan gorilla/websocket untuk dialog dua arah, SSE untuk push satu arah dengan format data:, streaming response dengan Flush, serta pola hub untuk broadcast ke banyak koneksi.
Inti yang harus dibawa pulang:
gorilla/websocket di handler Echo.CheckOrigin di production, jangan terima semua origin.text/event-stream dan format data: <pesan>.Flush mengirim data segera sebelum buffer penuh.Di episode 17 selanjutnya kita akan membahas testing & benchmark — unit test handler dengan echo.New() dan httptest, menguji middleware, mocking service dengan antarmuka, serta benchmark testing.B untuk mengukur alokasi dan latensi route.