gin+gorm實(shí)現(xiàn)goweb項(xiàng)目的示例代碼
Gin
Gin 是一個(gè)用 Go 編寫(xiě)的輕量級(jí)、高性能的 Web 框架。它的主要功能是處理 HTTP 請(qǐng)求和響應(yīng),幫助開(kāi)發(fā)者快速構(gòu)建 Web 應(yīng)用程序和 API 服務(wù)。
通俗解釋
Gin 框架就像一個(gè)服務(wù)員,負(fù)責(zé)接收客戶的訂單(HTTP 請(qǐng)求),根據(jù)菜單(路由規(guī)則)將訂單轉(zhuǎn)交給合適的廚師(處理函數(shù)),廚師準(zhǔn)備好食物(生成響應(yīng)數(shù)據(jù))后,服務(wù)員再將食物遞給客戶(返回 HTTP 響應(yīng))。
1. 主要功能
- 路由:Gin 允許你定義不同的 URL 路徑和 HTTP 方法(如 GET、POST),并將它們映射到相應(yīng)的處理函數(shù)。
- 中間件:可以在請(qǐng)求處理過(guò)程中插入多個(gè)中間件函數(shù),用于認(rèn)證、日志記錄等操作。
- 參數(shù)綁定:支持從 URL、表單、JSON 等位置獲取參數(shù)并綁定到結(jié)構(gòu)體中。
- 錯(cuò)誤處理:提供方便的錯(cuò)誤處理機(jī)制,統(tǒng)一管理錯(cuò)誤響應(yīng)。
2. 工作流程
- 定義路由:開(kāi)發(fā)者定義各種路由和它們對(duì)應(yīng)的處理函數(shù)。
- 啟動(dòng)服務(wù)器:Gin 框架啟動(dòng)一個(gè) HTTP 服務(wù)器,監(jiān)聽(tīng)特定端口。
- 接收請(qǐng)求:當(dāng)有 HTTP 請(qǐng)求到達(dá)時(shí),Gin 根據(jù)請(qǐng)求的路徑和方法查找對(duì)應(yīng)的處理函數(shù)。
- 執(zhí)行中間件:在處理函數(shù)執(zhí)行之前,依次執(zhí)行注冊(cè)的中間件。
- 處理請(qǐng)求:調(diào)用對(duì)應(yīng)的處理函數(shù),生成響應(yīng)數(shù)據(jù)。
- 返回響應(yīng):將響應(yīng)數(shù)據(jù)返回給客戶端。
3. 示例
package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "pong", }) }) r.Run(":8080") }
Gorm
Gorm 是一個(gè)用 Go 編寫(xiě)的 ORM(對(duì)象關(guān)系映射)庫(kù),它的主要功能是簡(jiǎn)化數(shù)據(jù)庫(kù)操作。Gorm 通過(guò)將數(shù)據(jù)庫(kù)表映射為 Go 結(jié)構(gòu)體,使得開(kāi)發(fā)者可以使用 Go 代碼來(lái)執(zhí)行數(shù)據(jù)庫(kù)的增刪改查等操作,而不需要直接編寫(xiě) SQL 語(yǔ)句。
通俗解釋:Gorm 就像一個(gè)翻譯器,它把開(kāi)發(fā)者寫(xiě)的 Go 代碼翻譯成數(shù)據(jù)庫(kù)能夠理解的 SQL 語(yǔ)句,并且負(fù)責(zé)執(zhí)行這些 SQL 語(yǔ)句,將結(jié)果再翻譯回 Go 語(yǔ)言的數(shù)據(jù)結(jié)構(gòu)。
1. 主要功能
- 模型定義:將數(shù)據(jù)庫(kù)表映射為 Go 結(jié)構(gòu)體,定義字段及其屬性。
- 查詢:提供簡(jiǎn)潔的查詢方法,如創(chuàng)建記錄、讀取記錄、更新記錄、刪除記錄等。
- 關(guān)系:支持?jǐn)?shù)據(jù)庫(kù)表之間的關(guān)系,如一對(duì)一、一對(duì)多、多對(duì)多關(guān)系。
- 遷移:自動(dòng)遷移數(shù)據(jù)庫(kù)表結(jié)構(gòu),使其與 Go 結(jié)構(gòu)體保持同步。
2. 工作流程
- 定義模型:開(kāi)發(fā)者定義與數(shù)據(jù)庫(kù)表對(duì)應(yīng)的 Go 結(jié)構(gòu)體。
- 初始化數(shù)據(jù)庫(kù)連接:配置數(shù)據(jù)庫(kù)連接信息,并建立連接。
- 執(zhí)行操作:使用 Gorm 提供的方法來(lái)進(jìn)行數(shù)據(jù)庫(kù)操作,如創(chuàng)建、查詢、更新、刪除等。
- 處理結(jié)果:將數(shù)據(jù)庫(kù)操作的結(jié)果映射回 Go 結(jié)構(gòu)體中,供業(yè)務(wù)邏輯使用。
3. 示例
package main import ( "gorm.io/driver/mysql" "gorm.io/gorm" "log" ) type User struct { ID uint `gorm:"primaryKey"` Name string `gorm:"size:255"` Email string `gorm:"uniqueIndex"` Age int } func main() { dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { log.Fatal(err) } // 自動(dòng)遷移 db.AutoMigrate(&User{}) // 創(chuàng)建記錄 db.Create(&User{Name: "John", Email: "john@example.com", Age: 25}) // 讀取記錄 var user User db.First(&user, 1) // 查詢主鍵為1的用戶 log.Println(user) // 更新記錄 db.Model(&user).Update("Age", 26) // 刪除記錄 db.Delete(&user) }
Gin+Gorm項(xiàng)目實(shí)操
1. 項(xiàng)目目錄結(jié)構(gòu)
my-gin-gorm-project/ │ ├── cmd/ │ └── main.go // 主程序入口 │ ├── config/ │ └── config.go // 配置文件解析 │ ├── controllers/ │ └── user.go // 用戶相關(guān)的控制器 │ ├── models/ │ └── user.go // 用戶模型定義 │ ├── routes/ │ └── routes.go // 路由定義 │ ├── middlewares/ │ └── auth.go // 認(rèn)證中間件 │ ├── services/ │ └── user.go // 用戶相關(guān)的業(yè)務(wù)邏輯 │ ├── repositories/ │ └── user.go // 用戶數(shù)據(jù)訪問(wèn)層 │ ├── utils/ │ └── utils.go // 工具函數(shù) │ ├── .env // 環(huán)境變量文件 ├── go.mod // Go模塊文件 └── go.sum // 依賴文件
2. 主程序入口(cmd/main.go)
package main import ( "my-gin-gorm-project/config" "my-gin-gorm-project/routes" "github.com/gin-gonic/gin" "gorm.io/gorm" ) var db *gorm.DB func main() { // 解析配置文件 config.LoadConfig() // 初始化數(shù)據(jù)庫(kù)連接 db = config.InitDB() // 設(shè)置Gin引擎 r := gin.Default() // 注冊(cè)路由 routes.RegisterRoutes(r) // 啟動(dòng)服務(wù)器 r.Run(config.Config.ServerPort) }
3. 配置文件解析(config/config.go)
package config import ( "log" "os" "github.com/joho/godotenv" "gorm.io/driver/mysql" "gorm.io/gorm" ) var Config struct { ServerPort string DBUser string DBPassword string DBName string DBHost string DBPort string } // LoadConfig 解析配置文件 func LoadConfig() { if err := godotenv.Load(); err != nil { log.Fatal("Error loading .env file") } Config.ServerPort = os.Getenv("SERVER_PORT") Config.DBUser = os.Getenv("DB_USER") Config.DBPassword = os.Getenv("DB_PASSWORD") Config.DBName = os.Getenv("DB_NAME") Config.DBHost = os.Getenv("DB_HOST") Config.DBPort = os.Getenv("DB_PORT") } // InitDB 初始化數(shù)據(jù)庫(kù)連接 func InitDB() *gorm.DB { dsn := Config.DBUser + ":" + Config.DBPassword + "@tcp(" + Config.DBHost + ":" + Config.DBPort + ")/" + Config.DBName + "?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { log.Fatal("Failed to connect to database:", err) } return db }
4. 用戶模型定義(models/user.go)
package models import "gorm.io/gorm" // User 用戶模型定義 type User struct { gorm.Model Name string `gorm:"size:255"` Email string `gorm:"uniqueIndex"` Age int }
5. 用戶相關(guān)的控制器(controllers/user.go)
package controllers import ( "my-gin-gorm-project/models" "my-gin-gorm-project/services" "net/http" "github.com/gin-gonic/gin" ) // GetUsers 獲取所有用戶 func GetUsers(c *gin.Context) { users := services.GetAllUsers() c.JSON(http.StatusOK, users) } // CreateUser 創(chuàng)建新用戶 func CreateUser(c *gin.Context) { var user models.User if err := c.ShouldBindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := services.CreateUser(&user); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, user) }
6. 用戶數(shù)據(jù)訪問(wèn)層(repositories/user.go)
package repositories import ( "my-gin-gorm-project/models" "gorm.io/gorm" ) var DB *gorm.DB // SetDB 設(shè)置數(shù)據(jù)庫(kù)實(shí)例 func SetDB(db *gorm.DB) { DB = db } // GetAllUsers 獲取所有用戶 func GetAllUsers() ([]models.User, error) { var users []models.User if err := DB.Find(&users).Error; err != nil { return nil, err } return users, nil } // CreateUser 創(chuàng)建新用戶 func CreateUser(user *models.User) error { if err := DB.Create(user).Error; err != nil { return err } return nil }
7. 用戶相關(guān)的業(yè)務(wù)邏輯(services/user.go)
package services import ( "my-gin-gorm-project/models" "my-gin-gorm-project/repositories" ) // GetAllUsers 獲取所有用戶 func GetAllUsers() []models.User { users, _ := repositories.GetAllUsers() return users } // CreateUser 創(chuàng)建新用戶 func CreateUser(user *models.User) error { return repositories.CreateUser(user) }
8. 路由定義(routes/routes.go)
package routes import ( "my-gin-gorm-project/controllers" "github.com/gin-gonic/gin" ) // RegisterRoutes 注冊(cè)所有路由 func RegisterRoutes(r *gin.Engine) { // 用戶相關(guān)路由 userRoutes := r.Group("/users") { userRoutes.GET("/", controllers.GetUsers) userRoutes.POST("/", controllers.CreateUser) } }
9. 環(huán)境變量文件(.env)
SERVER_PORT=:8080 DB_USER=root DB_PASSWORD=password DB_NAME=mydb DB_HOST=localhost DB_PORT=3306
10. 補(bǔ)充:關(guān)于utils和Middlewares的區(qū)別以及使用
Utils(工具類)
功能:工具類目錄用于存放項(xiàng)目中常用的工具函數(shù)和通用模塊。這些函數(shù)和模塊通常獨(dú)立于業(yè)務(wù)邏輯,可以在項(xiàng)目的各個(gè)部分復(fù)用。
存放內(nèi)容:
通用工具函數(shù):例如字符串處理函數(shù)、日期時(shí)間處理函數(shù)、加密解密函數(shù)等。
配置解析函數(shù):用于解析配置文件或環(huán)境變量的函數(shù)。
日志記錄函數(shù):處理日志記錄的工具。
Token處理:如Token的生成、解析、驗(yàn)證等。
其他通用模塊:如錯(cuò)誤處理函數(shù)、文件操作函數(shù)等。
示例
package utils import ( "time" "github.com/dgrijalva/jwt-go" "os" "errors" ) var jwtSecret = []byte(os.Getenv("JWT_SECRET")) // Claims 自定義的聲明 type Claims struct { UserID uint jwt.StandardClaims } // GenerateToken 生成Token func GenerateToken(userID uint) (string, error) { expirationTime := time.Now().Add(24 * time.Hour) claims := &Claims{ UserID: userID, StandardClaims: jwt.StandardClaims{ ExpiresAt: expirationTime.Unix(), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(jwtSecret) if err != nil { return "", err } return tokenString, nil } // ParseToken 解析Token func ParseToken(tokenString string) (*Claims, error) { claims := &Claims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { return jwtSecret, nil }) if err != nil { return nil, err } if !token.Valid { return nil, errors.New("invalid token") } return claims, nil }
Middlewares(中間件)
功能:中間件目錄用于存放在HTTP請(qǐng)求處理過(guò)程中需要執(zhí)行的額外操作。這些操作通常在請(qǐng)求到達(dá)具體的業(yè)務(wù)邏輯處理之前或之后進(jìn)行,主要用于請(qǐng)求的預(yù)處理和后處理。
存放內(nèi)容:
認(rèn)證中間件:如Token驗(yàn)證中間件,確保請(qǐng)求攜帶有效的Token。
日志中間件:記錄請(qǐng)求日志,包括請(qǐng)求的路徑、方法、響應(yīng)時(shí)間等。
錯(cuò)誤處理中間件:統(tǒng)一處理錯(cuò)誤并返回標(biāo)準(zhǔn)的錯(cuò)誤響應(yīng)。
CORS中間件:處理跨域請(qǐng)求。
其他預(yù)處理或后處理操作:如請(qǐng)求限流、壓縮響應(yīng)等。
示例
package middlewares import ( "my-gin-gorm-project/utils" "net/http" "strings" "github.com/gin-gonic/gin" ) // AuthMiddleware 認(rèn)證中間件 func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { tokenString := c.GetHeader("Authorization") if tokenString == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "請(qǐng)求頭中缺少Token"}) c.Abort() return } tokenString = strings.TrimPrefix(tokenString, "Bearer ") claims, err := utils.ParseToken(tokenString) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "無(wú)效的Token"}) c.Abort() return } c.Set("userID", claims.UserID) c.Next() } }
11. 項(xiàng)目運(yùn)行流程
- 配置解析和數(shù)據(jù)庫(kù)連接:在主程序入口中,首先加載配置文件并初始化數(shù)據(jù)庫(kù)連接。
- 路由注冊(cè):接著,注冊(cè)所有的路由。
- 控制器和服務(wù)層的調(diào)用:當(dāng)路由被訪問(wèn)時(shí),控制器會(huì)調(diào)用相應(yīng)的服務(wù)層方法。
- 數(shù)據(jù)訪問(wèn):服務(wù)層通過(guò)數(shù)據(jù)訪問(wèn)層(Repository)來(lái)進(jìn)行數(shù)據(jù)庫(kù)操作。
到此這篇關(guān)于gin+gorm實(shí)現(xiàn)goweb項(xiàng)目的示例代碼的文章就介紹到這了,更多相關(guān)gin+gorm實(shí)現(xiàn)goweb內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang gopm get -g -v 無(wú)法獲取第三方庫(kù)的解決方案
這篇文章主要介紹了golang gopm get -g -v 無(wú)法獲取第三方庫(kù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05go代碼實(shí)現(xiàn)買房貸款月供計(jì)算的方法
今天小編就為大家分享一篇關(guān)于go代碼實(shí)現(xiàn)買房貸款月供計(jì)算的方法,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-04-04Golang切片連接成字符串的實(shí)現(xiàn)示例
本文主要介紹了Golang切片連接成字符串的實(shí)現(xiàn)示例,可以使用Go語(yǔ)言中的內(nèi)置函數(shù)"String()"可以將字節(jié)切片轉(zhuǎn)換為字符串,具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11GoLang并發(fā)編程中條件變量sync.Cond的使用
Go標(biāo)準(zhǔn)庫(kù)提供Cond原語(yǔ)的目的是,為等待/通知場(chǎng)景下的并發(fā)問(wèn)題提供支持,本文主要介紹了Go并發(fā)編程sync.Cond的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下2023-01-01Golang算法問(wèn)題之?dāng)?shù)組按指定規(guī)則排序的方法分析
這篇文章主要介紹了Golang算法問(wèn)題之?dāng)?shù)組按指定規(guī)則排序的方法,結(jié)合實(shí)例形式分析了Go語(yǔ)言數(shù)組排序相關(guān)算法原理與操作技巧,需要的朋友可以參考下2017-02-02Go高效率開(kāi)發(fā)Web參數(shù)校驗(yàn)三種方式實(shí)例
這篇文章主要介紹了Go高效率開(kāi)發(fā)Web參數(shù)校驗(yàn)三種方式實(shí)例,需要的朋友可以參考下2022-11-11Go調(diào)度器學(xué)習(xí)之協(xié)作與搶占詳解
如果某個(gè)G執(zhí)行時(shí)間過(guò)長(zhǎng),其他的G如何才能被正常調(diào)度,這就引出了接下來(lái)的話題:協(xié)作與搶占。本文將通過(guò)一些示例為大家詳細(xì)講講調(diào)度器中協(xié)作與搶占的相關(guān)知識(shí),需要的可以參考一下2023-04-04