Step 00 — 05 | 從 Hello World 到即時聊天
gin.Default() = gin.New() + Logger + Recovery middleware。Logger 印每個 request 的資訊,Recovery 在 handler panic 時回 500 不讓 server 掛掉。
| Java (Spring) | Go (Gin) |
|---|---|
HttpServletRequest + HttpServletResponse | *gin.Context |
@RequestBody | c.ShouldBindJSON(&obj) |
ResponseEntity.ok(data) | c.JSON(200, data) |
request.getParameter("name") | c.Query("name") |
@PathVariable | c.Param("id") |
聊天室的核心是 Hub — 一個中樞,管理所有連線和訊息轉發。
select {
case client := <-h.Register: // 有人加入
case client := <-h.Unregister: // 有人離開
case message := <-h.Broadcast: // 有人說話
}
同時監聽多個 channel,誰先有資料就處理誰。Java 沒有對應語法,最接近的是 NIO Selector。
忘了啟動 writePump 會導致訊息送不出去 — Hub 廣播到 Client.Send 但沒人讀,瀏覽器收不到任何東西。
select {
case client.Send <- message: // 送成功
default: // 送不進去 → client 卡住了
close(client.Send) // 關掉
delete(h.Clients, client) // 踢掉
}
防止一個壞 client 卡住整個廣播迴圈。default 讓它不阻塞。
Gin 的 StaticFile("/") 會註冊 /*filepath 萬用路由,跟 /ws 衝突導致 panic。改用 StaticFS("/web") 掛在子路徑解決。
在 Register case 裡往 Broadcast channel 送訊息,但消費者也是同一個 select 迴圈 — 死結。解法:Register/Unregister 裡用 sendAll 直接發,不經過 Broadcast channel。
不是 yyyy-MM-dd,是固定參考時間 2006-01-02 15:04:05。寫錯數字會被當字面文字。