短短几十行,同时实现:
- 数据库自动迁移/自动建表
- 启动一个HTTP接口服务
- 从URL地址接收分页参数
- 完整查询
- 分页查询
- 表数据量查询
并且极易拓展新的表进行复用,后期拓展新的表查询仅仅需要加个结构体和仓库定义即可。
直接上示例
package main
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// 定义数据库user表结构体
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"type:varchar(255)" json:"username"`
}
// 泛型仓库结构
type customRepo[T any] struct {
DB *gorm.DB
}
// 用于存储不同表的数据库操作实例的全局变量
var (
UserRepo *customRepo[User]
)
// 初始化数据库仓库,为每个表的连接不同的数据库操作实例
func InitRepo(db *gorm.DB) {
UserRepo = NewRepo[UserRepo](db)
}
// 创建数据库操作实例
func NewRepo[T any](db *gorm.DB) *customRepo[T] {
return &customRepo[T]{DB: db}
}
// 实现分页查询, 计算总数并查询分页数据
func (br *customRepo[T]) FindData(page, limit int) (int64, []T, error) {
if page < 1 || limit < 1 {
return 0, nil, errors.New("Page和limit必须是正整数")
}
var count int64
if err := br.DB.Model(new(T)).Count(&count).Error; err != nil {
return 0, nil, err
}
offset := (page - 1) * limit
var dataSlice []T
if err := br.DB.Limit(limit).Offset(offset).Find(&dataSlice).Error; err != nil {
return 0, nil, err
}
return count, dataSlice, nil
}
// Gin处理函数,从url接收两个参数分别是limit和page, 可以不传自动默认值
func GetUserData(c *gin.Context) {
pageStr, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
limitStr, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
count, entities, err := UserRepo.FindData(pageStr, limitStr)
if err != nil {
c.JSON(500, gin.H{"code": 500, "message": err.Error()})
return
}
c.JSON(200, gin.H{
"data_count": count,
"data": entities,
})
}
func main() {
// 初始化数据库连接
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
return fmt.Errorf("数据库初始化失败: %w", err)
}
// 自动迁移
db.AutoMigrate(&User{})
// 初始化仓库
InitRepo(db)
// 设置Gin默认模式
r := gin.Default()
// 注册路由
r.GET("/", GetUserData)
// 运行服务器
r.Run(":8080")
}