提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
Gin
-
Gin 是一个用 Go 编写的轻量级、高性能的 Web 框架。它的主要功能是处理 HTTP 请求和响应,帮助开发者快速构建 Web 应用程序和 API 服务。
-
通俗解释
Gin 框架就像一个服务员,负责接收客户的订单(HTTP 请求),根据菜单(路由规则)将订单转交给合适的厨师(处理函数),厨师准备好食物(生成响应数据)后,服务员再将食物递给客户(返回 HTTP 响应)。
1. 主要功能
- 路由:Gin 允许你定义不同的 URL 路径和 HTTP 方法(如 GET、POST),并将它们映射到相应的处理函数。
- 中间件:可以在请求处理过程中插入多个中间件函数,用于认证、日志记录等操作。
- 参数绑定:支持从 URL、表单、JSON 等位置获取参数并绑定到结构体中。
- 错误处理:提供方便的错误处理机制,统一管理错误响应。
2. 工作流程
- 定义路由:开发者定义各种路由和它们对应的处理函数。
- 启动服务器:Gin 框架启动一个 HTTP 服务器,监听特定端口。
- 接收请求:当有 HTTP 请求到达时,Gin 根据请求的路径和方法查找对应的处理函数。
- 执行中间件:在处理函数执行之前,依次执行注册的中间件。
- 处理请求:调用对应的处理函数,生成响应数据。
- 返回响应:将响应数据返回给客户端。
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 是一个用 Go 编写的 ORM(对象关系映射)库,它的主要功能是简化数据库操作。Gorm 通过将数据库表映射为 Go 结构体,使得开发者可以使用 Go 代码来执行数据库的增删改查等操作,而不需要直接编写 SQL 语句。
-
通俗解释:Gorm 就像一个翻译器,它把开发者写的 Go 代码翻译成数据库能够理解的 SQL 语句,并且负责执行这些 SQL 语句,将结果再翻译回 Go 语言的数据结构。
1. 主要功能
- 模型定义:将数据库表映射为 Go 结构体,定义字段及其属性。
- 查询:提供简洁的查询方法,如创建记录、读取记录、更新记录、删除记录等。
- 关系:支持数据库表之间的关系,如一对一、一对多、多对多关系。
- 迁移:自动迁移数据库表结构,使其与 Go 结构体保持同步。
2. 工作流程
- 定义模型:开发者定义与数据库表对应的 Go 结构体。
- 初始化数据库连接:配置数据库连接信息,并建立连接。
- 执行操作:使用 Gorm 提供的方法来进行数据库操作,如创建、查询、更新、删除等。
- 处理结果:将数据库操作的结果映射回 Go 结构体中,供业务逻辑使用。
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)
}
// 自动迁移
db.AutoMigrate(&User{})
// 创建记录
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项目实操
1. 项目目录结构
my-gin-gorm-project/
│
├── cmd/
│ └── main.go // 主程序入口
│
├── config/
│ └── config.go // 配置文件解析
│
├── controllers/
│ └── user.go // 用户相关的控制器
│
├── models/
│ └── user.go // 用户模型定义
│
├── routes/
│ └── routes.go // 路由定义
│
├── middlewares/
│ └── auth.go // 认证中间件
│
├── services/
│ └── user.go // 用户相关的业务逻辑
│
├── repositories/
│ └── user.go // 用户数据访问层
│
├── utils/
│ └── utils.go // 工具函数
│
├── .env // 环境变量文件
├── 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()
// 初始化数据库连接
db = config.InitDB()
// 设置Gin引擎
r := gin.Default()
// 注册路由
routes.RegisterRoutes(r)
// 启动服务器
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 初始化数据库连接
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. 用户相关的控制器(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 创建新用户
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. 用户数据访问层(repositories/user.go)
package repositories
import (
"my-gin-gorm-project/models"
"gorm.io/gorm"
)
var DB *gorm.DB
// SetDB 设置数据库实例
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 创建新用户
func CreateUser(user *models.User) error {
if err := DB.Create(user).Error; err != nil {
return err
}
return nil
}
7. 用户相关的业务逻辑(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 创建新用户
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 注册所有路由
func RegisterRoutes(r *gin.Engine) {
// 用户相关路由
userRoutes := r.Group("/users")
{
userRoutes.GET("/", controllers.GetUsers)
userRoutes.POST("/", controllers.CreateUser)
}
}
9. 环境变量文件(.env)
SERVER_PORT=:8080
DB_USER=root
DB_PASSWORD=password
DB_NAME=mydb
DB_HOST=localhost
DB_PORT=3306
10. 补充:关于utils和Middlewares的区别以及使用
Utils(工具类)
-
功能:工具类目录用于存放项目中常用的工具函数和通用模块。这些函数和模块通常独立于业务逻辑,可以在项目的各个部分复用。
-
存放内容:
- 通用工具函数:例如字符串处理函数、日期时间处理函数、加密解密函数等。
- 配置解析函数:用于解析配置文件或环境变量的函数。
- 日志记录函数:处理日志记录的工具。
- Token处理:如Token的生成、解析、验证等。
- 其他通用模块:如错误处理函数、文件操作函数等。
-
示例
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请求处理过程中需要执行的额外操作。这些操作通常在请求到达具体的业务逻辑处理之前或之后进行,主要用于请求的预处理和后处理。
-
存放内容:
- 认证中间件:如Token验证中间件,确保请求携带有效的Token。
- 日志中间件:记录请求日志,包括请求的路径、方法、响应时间等。
- 错误处理中间件:统一处理错误并返回标准的错误响应。
- CORS中间件:处理跨域请求。
- 其他预处理或后处理操作:如请求限流、压缩响应等。
-
示例
package middlewares import ( "my-gin-gorm-project/utils" "net/http" "strings" "github.com/gin-gonic/gin" ) // AuthMiddleware 认证中间件 func AuthMiddleware() gin.HandlerFunc { return func(c *gin.Context) { tokenString := c.GetHeader("Authorization") if tokenString == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "请求头中缺少Token"}) c.Abort() return } tokenString = strings.TrimPrefix(tokenString, "Bearer ") claims, err := utils.ParseToken(tokenString) if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "无效的Token"}) c.Abort() return } c.Set("userID", claims.UserID) c.Next() } }
11. 项目运行流程
- 配置解析和数据库连接:在主程序入口中,首先加载配置文件并初始化数据库连接。
- 路由注册:接着,注册所有的路由。
- 控制器和服务层的调用:当路由被访问时,控制器会调用相应的服务层方法。
- 数据访问:服务层通过数据访问层(Repository)来进行数据库操作。