一,经典实用的项目目录结构
my-gin-project/
├── cmd/ # 项目入口 (遵循单一入口原则)
│ └── main.go # 初始化配置、数据库并启动服务
├── internal/ # 私有代码 (禁止被外部项目导入,保证业务隔离)
│ ├── config/ # 配置加载 (如读取 .env 或 yaml 文件)
│ │ └── config.go
│ ├── handler/ # 接口层 (接收HTTP请求、参数校验、调用Service)
│ │ └── user.go
│ ├── service/ # 业务逻辑层 (处理核心业务,调用Repository)
│ │ └── user.go
│ ├── repository/ # 数据访问层 (直接与数据库交互,如GORM操作)
│ │ └── user.go
│ ├── model/ # 数据模型 (对应数据库表结构)
│ │ └── user.go
│ ├── middleware/ # 中间件 (JWT鉴权、日志记录、跨域处理等)
│ │ └── auth.go
│ └── routes/ # 路由注册 (统一管理API路由和分组)
│ └── router.go
├── pkg/ # 公共库 (如封装的工具类、通用响应结构,允许外部导入)
├── .env # 环境变量配置
├── go.mod # Go 模块依赖管理
└── main.go # (可选) 也可以直接放在根目录二、 核心代码实现思路
框架搭建好后,各层之间的调用链通常是:Handler -> Service -> Repository。
初始化项目与安装依赖
首先初始化 Go 模块并安装 Gin 和GORM(常用的ORM框架)
mkdir my-gin-project && cd my-gin-project
go mod init my-gin-project
go get github.com/gin-gonic/gin
go get gorm.io/gorm
go get gorm.io/driver/mysql定义数据模型(internal/model/user.go)
使用GORM的标签来定义数据库表结构:
package model
import "gorm.io/gorm"
type User struct {
gorm.Model // 包含 ID, CreatedAt, UpdatedAt, DeletedAt(软删除)
Username string `gorm:"type:varchar(50);not null;uniqueIndex" json:"username"`
Email string `gorm:"type:varchar(100)" json:"email"`
}数据访问层(internal/repository/user.go)
负责所有与数据库打交道的操作:
package repository
import (
"my-gin-project/internal/model"
"gorm.io/gorm"
)
type UserRepository struct {
db *gorm.DB
}
func NewUserRepository(db *gorm.DB) *UserRepository {
return &UserRepository{db: db}
}
func (r *UserRepository) CreateUser(user *model.User) error {
return r.db.Create(user).Error
}业务逻辑层(internal/service/user.go)
处理具体的业务规则,解耦 Handler 和数据库
package service
import (
"my-gin-project/internal/model"
"my-gin-project/internal/repository"
)
type UserService struct {
userRepo *repository.UserRepository
}
func NewUserService(userRepo *repository.UserRepository) *UserService {
return &UserService{userRepo: userRepo}
}
func (s *UserService) Register(user *model.User) error {
// 这里可以加入密码加密、业务校验等逻辑
return s.userRepo.CreateUser(user)
}接口层(internale/handler/user.go)
处理HTTP请求,绑定参数并返回响应
package handler
import (
"net/http"
"my-gin-project/internal/model"
"my-gin-project/internal/service"
"github.com/gin-gonic/gin"
)
type UserHandler struct {
userService *service.UserService
}
func NewUserHandler(userService *service.UserService) *UserHandler {
return &UserHandler{userService: userService}
}
func (h *UserHandler) Register(c *gin.Context) {
var req model.User
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if err := h.userService.Register(&req); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "注册失败"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "注册成功", "data": req})
}路由与入口(cmd/main.go)
将各层组装起来,启动服务:
package main
import (
"my-gin-project/internal/config"
"my-gin-project/internal/handler"
"my-gin-project/internal/repository"
"my-gin-project/internal/routes"
"my-gin-project/internal/service"
// 引入数据库驱动和Gin等...
)
func main() {
// 1. 加载配置与初始化数据库 (伪代码)
// cfg := config.LoadConfig()
// db := database.InitDB(cfg)
// 2. 依赖注入 (将下层对象注入到上层)
userRepo := repository.NewUserRepository(db)
userService := service.NewUserService(userRepo)
userHandler := handler.NewUserHandler(userService)
// 3. 设置路由并启动
router := routes.SetupRouter(userHandler)
router.Run(":8080")
}实用建议:
统一响应格式:在
pkg目录下封装一个response工具,统一返回给前端的 JSON 格式(如包含code,message,data字段),避免在每个 Handler 里重复写c.JSON。配置管理:使用 Viper 库来读取
.env或yaml配置文件,方便管理不同环境(开发、测试、生产)的配置。日志系统:集成 Zap 或 Logrus,替代默认的日志打印,支持日志分级、文件切割和格式化输出。
API 文档:集成 Swaggo (Swagger),通过注释自动生成 RESTful API 文档,极大提升前后端协作效率。
优雅退出与热重载:开发阶段可以使用
air实现代码修改后自动重启;生产环境注意处理服务的优雅退出。
三,Swaggo生成API文档
1,安装Swaggo依赖
# 安装 Swaggo 命令行工具
go install github.com/swaggo/swag/cmd/swag@latest
# 安装 Gin 框架的 Swaggo 中间件和静态文件依赖
go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files2,编写规范的注释
Swaggo 需要两类注释:全局 API 描述和接口具体描述。
package main
// @title 你的项目名称 API
// @version 1.0
// @description 基于Gin框架搭建的RESTful API文档
// @termsOfService http://swagger.io/terms/
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host localhost:8080
// @BasePath /api/v1
// @schemes http https
func main() {
// ... 你的 main 函数逻辑
}接口注释(放在 internal/handler/user.go 的具体接口方法上方)
package handler
import (
"my-gin-project/internal/model"
"github.com/gin-gonic/gin"
)
// Register 用户注册
// @Summary 注册新用户
// @Description 传入用户名和密码,完成用户注册
// @Tags 用户模块
// @Accept json
// @Produce json
// @Param user body model.User true "用户信息"
// @Success 200 {object} map[string]interface{} "注册成功"
// @Failure 400 {object} map[string]interface{} "请求参数错误"
// @Router /users/register [post]
func (h *UserHandler) Register(c *gin.Context) {
// ... 你的业务逻辑
}3,生成文档文件
// 在项目根目录下执行
swag init -g cmd/main.go -o ./docs4,在Gin中注册Swagger路由
回到 cmd/main.go,导入生成的 docs 包,并在路由中挂载 Swagger 的处理函数:
package main
import (
// 必须导入生成的 docs 包,否则无法加载文档
_ "my-gin-project/docs"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)
func main() {
// ... 初始化配置、数据库、依赖注入等逻辑
router := gin.Default()
// 注册 Swagger 路由,访问路径为 /swagger/index.html
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
// ... 注册你的业务路由
// routes.SetupRouter(router, userHandler)
router.Run(":8080")
}5,访问可视化文档
启动 Gin 项目(go run cmd/main.go),然后在浏览器中打开以下地址:http://localhost:8080/swagger/index.html
备注:
自动化更新:每次修改了接口或注释后,只需重新运行
swag init命令,文档就会自动更新。多版本管理:如果项目有
v1、v2等多个版本,可以利用swag init的--instanceName参数(例如swag init --instanceName v1 -d ./internal/v1)生成多份独立的文档,并在 Gin 中通过不同的路由前缀进行挂载。
四,Go项目环境
Go 语言没有也不需要像 Python 那样为每个项目创建独立的虚拟环境(venv)。
Go 从 1.11 版本引入、1.16 版本起默认启用的 Go Modules 机制,已经完美解决了 Python venv 想要解决的问题:
项目级依赖声明:每个项目根目录下的
go.mod文件明确声明了该项目所需的所有依赖及其精确版本。多版本共存:如果项目 A 需要
gin@v1.9.0,项目 B 需要gin@v1.10.0,Go 会在系统缓存中同时保留两个版本,各自的项目只会引用自己go.mod中声明的版本,绝对不会互相污染。可复现构建:
go.sum文件记录了所有依赖的加密校验和,确保在任何机器上构建出的结果完全一致。
如果需要项目级隔离,可以通过设置环境变量实现类似效果:
# 在项目根目录下执行
export GOPATH=$(pwd)/.gopath
export GOMODCACHE=$(pwd)/.gopath/pkg/mod
# 之后该项目的所有依赖都会下载到项目内的 .gopath 目录中
go mod download直接开始
直接
go mod init即可开始新项目。Go 的
go.mod= Python 的requirements.txt+venv的组合体,且更加高效。Gin 项目框架中,
go.mod和go.sum就已经承担了完整的依赖隔离职责,无需额外配置任何虚拟环境。