项目介绍
使用gin
+ gorm
实现分页,按一般的mvc
架构思想去划分目录,良好的编码习惯是用Dao
层去查询数据库,Server
层去实现业务逻辑(此案例业务逻辑简单所以没有封装)。
第三方库
gin
gorm
以及对应的mysql
驱动包
目录结构
├── README.md
├── config
│ └── config.go
├── controller
│ └── user.go
├── dao
│ └── user.go
├── data.sql
├── go.mod
├── go.sum
├── main.go
├── model
│ ├── page.go
│ └── user.go
├── routes
│ └── routes.go
└── utils
└── pagination.go
config
目录
var DB *gorm.DB
func init() {
var err error
DB, err = gorm.Open(mysql.Open("帐号:密码@tcp(数据库连接地址:3306)/数据库名?charset=utf8mb4&parseTime=True&loc=Local"))
if err != nil {
panic(err)
}
var db *sql.DB
db, err = DB.DB()
if err != nil {
panic(err)
}
// 设置打开数据库连接最大数量
db.SetMaxOpenConns(100)
// 设置空闲连接池连接的最大数量
db.SetMaxIdleConns(10)
// 设置连接最大可复用时间
db.SetConnMaxLifetime(time.Hour)
db.SetConnMaxIdleTime(time.Hour)
// 自动迁移
if err := DB.AutoMigrate(&model.User{}); err != nil {
log.Panicf("自动迁移失败: %s", err)
}
}
该目录主要存放配置信息,这里主要是设置gorm
的连接配置,定义好模型后还可以自动迁移,相比较Laravel
框架的迁移方便多了。
controller
目录
定义用户控制器,与路由直接绑定:
func GetAllUser(c *gin.Context) {
pagination := utils.GeneratePaginationFromRequest(c)
// 这里可以组装查询条件
var user model.User
users, err := dao.GetAllUsers(&user, &pagination)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err,
})
return
}
c.JSON(http.StatusOK, gin.H{
"data": users,
})
}
dao
目录
直接查询数据库,这样可以保证Model
层的简洁,一般在Laravel
框架我只在Model
层定义关联关系,查询都是放在Dao
层,Spring Boot
框架也是如此设计。
func GetAllUsers(user *model.User, pagination *model.Pagination) (users []model.User, err error) {
// 分页查询
offset := (pagination.Page - 1) * pagination.Limit
err = config.DB.Where(user).Limit(pagination.Limit).Offset(offset).Order(pagination.Sort).Find(&users).Error
return
}
model
目录
page
文件
定义分页的结构体:
type Pagination struct {
Limit int `json:"limit" form:"limit" uri:"limit"`
Page int `json:"page" form:"page" uri:"page"`
Sort string `json:"sort" form:"sort" uri:"sort"`
}
user
文件
定义用户模型:
type User struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"varchar(20);comment:'用户名称'" json:"name"`
Email string `gorm:"comment:'邮箱'" json:"email"`
CreatedAt time.Time `gorm:"autoCreateTime;comment:'创建时间'" json:"created_at"`
UpdatedAt time.Time `gorm:"autoUpdateTime;comment:'操作事件'" json:"updated_at]"`
}
routes
目录
定义路由规则:
func SetUpRouter() *gin.Engine {
r := gin.Default()
user := r.Group("/user")
{
user.GET("all", controller.GetAllUser)
}
return r
}
utils
目录
辅助函数,类似Laravel
框架的helper
:
func GeneratePaginationFromRequest(c *gin.Context) (pagination model.Pagination) {
if err := c.ShouldBind(&pagination); err != nil {
fmt.Printf("参数绑定错误:%s\n", err)
}
// 校验参数
if pagination.Limit < 0 {
pagination.Limit = 2
}
if pagination.Page < 1 {
pagination.Page = 1
}
if len(pagination.Sort) == 0 {
pagination.Sort = "created_at desc"
}
return
}
测试sql
insert into users (`name`, `email`, `created_at`, `updated_at`) values ("chris", "aaaa@chris.com", "2022-07-13 18:00:00", "2022-07-13 18:00:00");
insert into users (`name`, `email`, `created_at`, `updated_at`) values ("张三", "zhangsan@chris.com", "2022-07-13 18:00:00", "2022-07-13 18:00:00");
insert into users (`name`, `email`, `created_at`, `updated_at`) values ("李四", "lisi@chris.com", "2022-07-13 18:00:00", "2022-07-13 18:00:00");
insert into users (`name`, `email`, `created_at`, `updated_at`) values ("王五", "wangwu@chris.com", "2022-07-13 18:00:00", "2022-07-13 18:00:00");
main
函数
上述代码都完成后,就可以运行测试:
func main() {
router := routes.SetUpRouter()
err := router.Run(":8080")
if err != nil {
panic(err)
}
}