Gin
是一個非常輕量且高效能的網頁框架,適合用來構建 RESTful APIs
或 Web
應用程式。它因為簡單易用、效能優異以及強大的路由功能,成為許多 Golang 開發者的首選。
那我會選擇他來介紹是因爲 Gin
在處理大量的 HTTP 請求時能夠保持較高的效能,即使在高流量場景下也能有非常快速的響應。
一樣在 terminal 下方輸入這段指令
go get -u github.com/gin-gonic/gin
確保在 go.mod 有下面內容
module demo
go 1.23.0
require github.com/gin-gonic/gin v1.10.0
require (
github.com/bytedance/sonic v1.12.3 // indirect
github.com/bytedance/sonic/loader v0.2.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.22.1 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.10.0 // indirect
golang.org/x/crypto v0.27.0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/text v0.18.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
那這是我會介紹到的檔案結構,除了 handle
和 repository
的具體實現會留到之後介紹外,剩下的會帶大家做個小複習!
demo/
├── main.go
├── handler/
│ ├── userHandler.go
├── repositories/
│ ├── userRepo.go
├── database/
│ └── db.go
├── ├── models/
│ └── userModel.go
└── routes/
└── routes.go
首先是我們的 /demo/database
底下的內容。
userModel.go
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:255"`
Age int
}
db.go
package database
import (
"demo/database/models"
"fmt"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Database struct {
Context *gorm.DB
}
var DB *Database
func ConnectDB() {
dsn := "host=localhost user=imac dbname=mydb port=5432 sslmode=disable timezone=Asia/Taipei"
var db *gorm.DB
var err error
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
} else {
fmt.Println("connected success")
}
if err := db.AutoMigrate(&models.User{}); err != nil {
panic("failed to auto migrate")
} else {
migrator := db.Migrator()
migrator.HasTable(&models.User{})
}
DB = &Database{
Context: db,
}
}
跟之前的連接資料庫不同的地方在於,我們對此做了一些小調整
Database
結構體:封裝了資料庫連線,讓操作資料庫更加結構化。ConnectDB
函數:負責建立資料庫連線、處理錯誤、自動進行資料表遷移,並且將連線存儲在全域變數 DB 中。最後我們將建立好的資料庫連線(
db
)包裝進Database
結構體,並賦值給全域變數DB
,這樣應用的其他地方就可以通過DB.Context
來存取資料庫,進行查詢、插入、更新等操作,而不必擔心重複建立資料庫連線。
再來是我們的 /demo/handler
userHandler.go
package handler
import (
"github.com/gin-gonic/gin"
)
/*
- 查詢 (Query)
- Get
- GetAll
- 修改 (Modify)
- Create
- Update
- Delete
*/
func GetHandle(context *gin.Context) {
}
func GetAllHandle(context *gin.Context) {
}
func CreateHandle(context *gin.Context) {
}
func UpdateHandle(context *gin.Context) {
}
func DeleteHandle(context *gin.Context) {
}
下篇會再做更詳細的介紹。
接著我們來實現路由的部分 demo/routes
在 API 開發中,路由(Router)是負責將 HTTP 請求(如 GET、POST、PUT、DELETE 等)導向對應處理函數的核心組件。簡單來說,當一個請求到達伺服器時,路由會根據請求的 URL 路徑和 HTTP 方法,決定應該由哪個處理函數來處理這個請求。
routes.go
package routes
import (
api "demo/handler"
"github.com/gin-gonic/gin"
"log"
)
type rawValue string
const (
// User Profile
UserProfile rawValue = "/user/:id"
User rawValue = "/user"
UserList rawValue = "/users"
)
func InitRouter() {
app := gin.Default()
// 設定代理伺服器的 IP 或網域
trustedProxies := []string{"127.0.0.1"} // 設定本地開發環境
if err := app.SetTrustedProxies(trustedProxies); err != nil {
log.Fatalf("設定信任的代理伺服器失敗: %v", err)
}
userApi := app.Group("/api/v1")
{
// User Identity
userApi.GET(string(UserProfile), api.GetHandle)
userApi.GET(string(UserList), api.GetAllHandle)
userApi.POST(string(User), api.CreateHandle)
userApi.PUT(string(User), api.UpdateHandle)
userApi.DELETE(string(User), api.DeleteHandle)
}
err := app.Run(":8080")
if err != nil {
panic(err)
}
}
InitRouter
方法
gin.Default()
:返回一個包含預設中介軟體的路由器實例。SetTrustedProxies
:設定應用程式信任的代理伺服器,確保應用程式只信任來自特定來源的代理。因為我們只是在開發環境中,所以通常設為 127.0.0.1(本地回環地址)。app.Group("/api/v1")
:創建一個路由群組,所有在此群組下定義的路由都會有共同的前綴 /api/v1
。這有助於版本管理和路由組織。app.Run(":8080")
:啟動 HTTP 伺服器,監聽本機的 8080 埠。若啟動失敗,將觸發 panic,終止應用程式。main.go
package main
import (
"demo/database"
"demo/routes"
)
func main() {
database.ConnectDB()
routes.InitRouter()
}
接著我們試著執行程式看看,會出現什麼吧!
[GIN-debug] GET /api/v1/users --> demo/handler.GetAllHandle (3 handlers)
[GIN-debug] POST /api/v1/user --> demo/handler.CreateHandle (3 handlers)
[GIN-debug] PUT /api/v1/user --> demo/handler.UpdateHandle (3 handlers)
[GIN-debug] DELETE /api/v1/user --> demo/handler.DeleteHandle (3 handlers)
[GIN-debug] Listening and serving HTTP on :8080
那可以看到他已經在我們本地的8080埠號啟動了,那今天就先到這邊,明天我們再來接續下面的內容!
在本篇介紹中,我們搭建了一個基於 Gin
框架的基本 Go 專案結構,涵蓋了資料庫連接、模型定義、路由設置及處理函數的基礎實作。通過使用 GORM
進行資料庫操作,我們確保了資料庫連線的結構化管理和自動遷移功能。同時,通過路由群組的方式,有效地組織了 API 路由,並設置了信任的代理伺服器以增強應用的安全性。最後,我們成功啟動了伺服器,並確認了各個路由的正確配置。接下來,將進一步實作具體的處理函數,完成完整的 CRUD 操作。
如果需要嘗試其他解決方案可以參考下面這些框架來開發