iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0
Software Development

Go Clean Architecture API 開發全攻略系列 第 6

Gin 框架開發實戰(一):路由設計 及 Middleware 應用

  • 分享至 

  • xImage
  •  

建立 Golang Web Server 常見選擇:

  • net/http(標準庫):穩定、無外部依賴,但需撰寫較多樣板碼。
  • Gin:輕量、速度快,路由設計彈性高,社群活躍。
  • Echo、Fiber:語法類似 Gin,各有不同設計哲學。
  • Beego、Revel:全功能框架,適合大型專案,但學習曲線較陡峭。

為什麼選擇 Gin?

  • 性能優越:Gin 基於 httprouter,性能表現優異,適合高併發場景。
  • 易於使用:語法簡潔,學習曲線平緩,適合快速開發。
  • 豐富的中介軟體: Gin 提供多種內建中介軟體,且易於自訂。
  • 活躍的社群:擁有大量使用者和豐富的資源,方便尋求支援。

本文將示範如何在 Clean Architecture 架構下,設計清晰且易於維護的路由層。

結構解析

  • internal/http/server.go: 負責 http.Server 的生命週期管理,包括 graceful shutdown。
  • internal/http/middleware/*.go: 定義全域中介軟體,如日誌、CORS、錯誤處理等。
  • internal/http/route.go: 路由的總入口,負責註冊全域中介軟體和呼叫特定路由的設定函式。
  • internal/http/route_api.go: 負責註冊所有 /api API 相關的路由。
  • internal/http/route_root.go: 負責註冊根路由,如健康檢查、靜態資源等。

程式碼實踐

接下來,我們將深入探討每個檔案的具體實作。

server.go:HTTP 伺服器的啟動 與 Graceful Shutdown

server.go 的核心職責是管理 http.Server 的完整生命週期。

一個良好的伺服器不僅要能正確啟動,更重要的是能在接收到關閉信號時(例如 Ctrl+Ckill 命令),實現 Graceful Shutdown。

設定伺服器

我們使用 http.Server 來設定伺服器的基本參數,如地址、處理器(Handler)、讀寫逾時等。

internal/http/server.go

func NewServer(app *application.Application) (*Server, error) {
	engine := gin.New()

	engine.Use(gin.Recovery())
	engine.Use(middleware.NewRequestLogger(app.Logger).Execute())
	engine.Use(middleware.NewInjectLogger(app.Logger).Execute())

	registerRoutes(engine, app)

	server := &http.Server{
		Addr:        ":" + app.Config.Server.Port,
		Handler:     engine,
		ReadTimeout: defaultHTTPServerReadHeaderTimeout,
	}

	return &Server{
		server: server,
		engine: engine,
	}, nil
}

我們使用的 gin.New() 來建立一個新的 Gin 引擎,
註冊了一個 gin 內建的 Recovery Middleware,
以及兩個自訂的 Middleware:RequestLoggerInjectLogger

為什麼會需要 Recovery Middleware 呢?因為它能捕捉任何未處理的 panic,
防止伺服器直接被關閉,並回應 500 錯誤給客戶端。
但是如果你的服務器架構有監控系統(如 Kubernetes),你也可以選擇不使用 Recovery Middleware,
讓服務器在發生 panic 時直接崩潰,然後由監控系統自動開啟新的 Server Instance 來處理請求。

Graceful Shutdown

Graceful Shutdown 意味著:

  1. 停止接收新的請求。
  2. 等待目前正在處理的請求完成。
  3. 關閉伺服器,釋放資源。

這樣可以避免中斷正在執行的操作,確保資料一致性,並提升系統的可靠性。

route.go:路由的總指揮

route.go 是路由設定的總入口。它的職責很單純:

  1. 使用 gin.Engine 實例。
  2. 註冊 Middleware,這些 Middleware 會應用於所有請求。
  3. 將不同路徑的 Route 註冊委派給其他 route_*.go 檔案。
  4. 傳遞 application.Application 物件,讓各個路由設定函式能夠存取應用程式的服務。
    至於這裡為什麼要傳遞 application.Application 物件呢?這是要完成 Deep Dependency Injection 的目的。
    詳細的使用細節,之後章節會說明。

這種做法讓路由管理更有條理。當專案規模擴大時,
我們可以輕易地新增 route_admin.goroute_v2.go 等檔案,
而不需要修改 route.go 的核心邏輯。

route_root.go & route_api.go:模組化的路由註冊

這兩個檔案分別定義了不同路徑前綴的路由。

  • route_root.go:通常用於註冊服務狀態相關的端點,例如健康檢查 (/healthz) 或指標 (/metrics)。
  • route_api.go:是 API 的主要入口,所有業務邏輯相關的 API 都會在這裡註冊,並以 /api 作為前綴。

我們會在之後的篇章中,詳細介紹如何在 route_api.go 中註冊具體的 API 路由。

middleware:中介層

Middleware 是 Gin 框架的核心優勢之一。
它允許我們在請求處理流程中插入自訂邏輯,
非常適合處理日誌、認證、CORS、錯誤恢復等。

在我們的架構中,internal/http/middleware 目錄存放了所有自訂的中介軟體。

目前我們實作了兩個 Middleware:

  • RequestLogger:負責記錄每個請求的詳細資訊,如方法、路徑、狀態碼、處理時間等。
  • InjectLogger:將 Logger 注入到 Gin 的 Context 中,讓後續的處理程式碼可以方便地使用 logger。

總結

本文介紹了如何在 Clean Architecture 架構下,使用 Gin 框架設計清晰且易於維護的路由層。
我們探討了伺服器的生命週期管理、路由的模組化,以及 Middleware 的應用。
這種結構不僅提升了程式碼的可讀性和可維護性,也為未來的擴展和修改奠定了基礎。

以上程式碼的完整內容可以到 Github 觀看


上一篇
目錄結構的藝術:一個清晰的 Go 專案應該長什麼樣子?
系列文
Go Clean Architecture API 開發全攻略6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言