iT邦幫忙

2025 iThome 鐵人賽

DAY 3
0
Modern Web

Golang x Echo 30 天:零基礎GO , 後端入門系列 第 3

入門 Echo 框架:從 Hello, World 到優雅關閉

  • 分享至 

  • xImage
  •  

為什麼要用 Echo?

還記得我們第一篇提到的,選擇 Go 語言的原因嗎?

高效率、併發性強,這些都是 Go 的優勢。

Echo 就像是為 Go 量身打造的「跑車」,它輕巧、快速,而且 API 設計得非常直覺易懂。

設想一下,你打算開設一家餐廳(這就是你的 Web 服務),需要一套點餐系統(對應路由),還有廚房(用來處理請求的函式,也就是 handler),當然也少不了負責收錢和送餐的人員(回應)。Echo 框架能協助你準備好所有這些流程,讓你專心開發「菜色」(也就是你的應用邏輯),不必把寶貴的時間浪費在煩惱「廚房怎麼蓋」、「菜單怎麼排」之類的問題。

Echo 的特色包括:
1.豐富的功能:路由、參數綁定、中介軟體 (Middleware)、模板渲染等,該有的都有。
2.簡潔的 API:語法清晰,學習曲線平緩。
3.高度可擴展性:你可以輕鬆加入自訂的功能。

準備好你的第一個 Echo 應用:Hello, World!
正所謂工欲善其事,必先利其器。我們在上一篇文章已經安裝好了 Go 環境,現在就來寫下你的第一個 Echo 應用吧!

首先,務必確認你的專案已經初始化了 Go modules。如果還沒做,回到你的專案目錄,執行:

go mod init your_module_name # 替換成你自己的 module name

接著,我們需要安裝 Echo 套件。執行:

go get github.com/labstack/echo/v4

現在,在你的 main.go 檔案裡,輸入以下程式碼:

package main

import (
	"net/http"
	"github.com/labstack/echo/v4"
)

func main() {
	// 1) 開一間餐廳(建立 Echo)
	e := echo.New()

	// 2) 菜單:有人用 GET 訪問首頁 "/",要回什麼
	e.GET("/", func(c echo.Context) error {
		// 3) 廚房出餐:回一段文字 + 成功狀態碼 200
		return c.String(http.StatusOK, "Hello, Echo!")
	})

	// 4) 開門營業:在 8080 埠口等大家
	e.Logger.Fatal(e.Start("0.0.0.0:8080"))
}

這段程式在做什麼
把程式想成餐廳:

  1. 開餐廳 → 建立一個 Echo 應用(echo.New())
  2. 寫菜單 → 設定路由「有人點 / 這道菜就回一句話」(e.GET("/", ...))
  3. 出餐 → 廚房(Handler)把「Hello, Echo!」端出去(c.String(...))
  4. 開門營業 → 在 0.0.0.0:8080 開門等客人(e.Start(...))
    每一行到底做了什麼
    1.echo.New():開一間新餐廳,準備接客。
    2.e.GET("/", handler):定義「有人到首頁 /,就叫這位廚師(handler)做菜」。
    3.func(c echo.Context) error { ... }:廚師本人。c 是來回傳菜的托盤。
    4.c.String(http.StatusOK, "Hello, Echo!"):把「Hello, Echo!」裝盤,附上「200 OK」代表成功。
    5.e.Start("0.0.0.0:8080"):把餐廳門口開在 8080 號門牌,任何網卡都能進來。

優雅關閉 (Graceful Shutdown) 的重要性
在 Web 服務開發中,有一個非常重要的概念,那就是「優雅關閉」。想像一下,你正在享受美味的晚餐,餐廳突然停電了,所有人都被趕了出去,是不是很掃興?優雅關閉就像是餐廳在打烊前,先通知客人,讓他們有時間吃完飯,然後才慢慢關燈、打掃,確保每個人都能安心離開。

在軟體世界裡,優雅關閉指的是伺服器在收到關閉指令時,不是立刻停止服務,而是 先完成目前正在處理的請求,等到所有工作都告一段落後,再逐步關閉。這樣可以避免資料遺失、請求中斷等問題,提升使用者體驗。
在 Echo 中,實現優雅關閉其實並不難。我們只需要在 main 函式中稍微修改一下:

package main

import (
	"net/http"
	"os"      // 引入 os 套件,用於接收系統訊號
	"os/signal" // 引入 signal 套件,用於處理系統訊號
	"time"    // 引入 time 套件,用於設定等待時間

	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()

	e.GET("/", func(c echo.Context) error {
		// 模擬一個比較耗時的請求
		time.Sleep(5 * time.Second)
		return c.String(http.StatusOK, "Hello, Echo!")
	})

	// 啟動伺服器
	go func() {
		if err := e.Start("0.0.0.0:8080"); err != nil && err != http.ErrServerClosed {
			e.Logger.Fatalf("shutting down the server: %v", err)
		}
	}()

優雅關閉程式碼實作與測試
好的,現在讓我們來看看如何實際修改程式碼,為你的 Echo 應用程式加入「優雅關閉」的功能。這部分的程式碼稍微複雜一些,但別擔心,我會一步一步帶著你理解。
首先,讓我們來看看修改後的完整程式碼:

package main

import (
	"context"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

func main() {
	// Echo instance
	e := echo.New()

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())

	// Route => handler
	e.GET("/", func(c echo.Context) error {
		time.Sleep(10 * time.Second) // 模擬耗時操作
		return c.String(http.StatusOK, "Hello, Echo!")
	})

	// Start server in a goroutine
	go func() {
		if err := e.Start(":8080"); err != nil && err != http.ErrServerClosed {
			e.Logger.Fatal("Shutting down the server")
		}
	}()

	// 建立一個 channel,用於接收中斷訊號
	quit := make(chan os.Signal, 1)
	// 監聽 SIGINT (Ctrl+C) 和 SIGTERM (關閉指令)
	signal.Notify(quit, os.Interrupt, syscall.SIGTERM) // 這裡需要引入 "syscall" 套件

	// 阻塞,直到收到訊號
	<-quit
	e.Logger.Info("Shutting down server gracefully...")

	// 建立一個帶有超時的 context,防止無限期等待
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) // 這裡需要引入 "context" 套件
	defer cancel() // 確保 context 在函數結束時被取消

	// 執行優雅關閉
	if err := e.Shutdown(ctx); err != nil {
		e.Logger.Fatal(err)
	}

	e.Logger.Info("Server shut down successfully")
}

程式碼詳解
現在,讓我們逐行拆解這些修改,瞭解它們的作用:

  1. go func() { ... }():我們使用 goroutine 啟動 Echo 伺服器。 這麼做的好處是可以讓 main 函式繼續往下執行,處理關閉的邏輯,而不會被 e.Start() 阻塞。
  2. quit := make(chan os.Signal, 1):建立一個 channel。 這個 channel 用於接收作業系統傳送的訊號,例如關閉或中斷指令。
  3. signal.Notify(quit, os.Interrupt, syscall.SIGTERM): 這一行告訴作業系統,當使用者按下 Ctrl+C (os.Interrupt) 或者系統發送 SIGTERM 訊號時,將這些訊號傳送到 quit 這個 channel。 你需要 import syscall 這個 package。
  4. <-quit:這行程式碼會讓 main 函式「暫停」在這裡, 直到 quit channel 接收到訊號才會繼續執行。 簡單來說,程式會在這裡等待,直到你按下 Ctrl+C 或系統發出關閉指令。
  5. context.WithTimeout(...):建立一個帶有 超時時間的 context。 就算伺服器因為某些原因無法正常關閉,我們最多隻會等待 10 秒鐘。 這可以避免程式卡住,保證最終能夠結束。 你需要 import context 這個 package。
  6. defer cancel():使用 defer 確保 context 在函數結束時一定會被取消。
  7. e.Shutdown(ctx):這是 Echo 框架提供的 優雅關閉方法。 它會停止接受新的請求,並等待正在處理的請求完成(在 context 設定的超時時間內)。
    如何測試優雅關閉?

瞭解程式碼後,最重要的就是實際測試,確認優雅關閉是否真的有效!

  1. 首先,執行 go run main.go 啟動伺服器。
  2. 接著,打開瀏覽器,訪問 http://localhost:8080
  3. 在伺服器還在處理請求時(你可以觀察終端機,在印出 "Hello, Echo!" 訊息之前),按下 Ctrl+C。
  4. 如果一切正常,你會在終端機上看到伺服器印出「Shutting down server gracefully...」,然後等待一段時間,最後印出「Server shut down successfully」。

如果看到這些訊息,恭喜你! 你的 Echo 伺服器已經成功實現了 優雅關閉 功能!

/images/emoticon/emoticon12.gif
通過這個簡單的範例,你現在應該對如何在 Echo 框架中實現優雅關閉有了更深入的瞭解。


上一篇
安裝 Go 與工具:打造你的第一個開發環境
下一篇
Echo 路由設計與參數處理:像在速食店點餐一樣簡單
系列文
Golang x Echo 30 天:零基礎GO , 後端入門4
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言