model.go

package database

import (
	"gorm.io/gorm"
)

type Page[T any] struct {
	CurrentPage int64
	PageSize    int64
	Total       int64
	Pages       int64
	Data        []T
}

func (page *Page[T]) SelectPage(wrapper map[string]interface{}) (e error) {
	e = nil
	var model T
	DB.Model(&model).Where(wrapper).Count(&page.Total)
	if page.Total == 0 {
		page.Data = []T{}
		return
	}
	e = DB.Model(&model).Where(wrapper).Scopes(Paginate(page)).Find(&page.Data).Error
	return
}

func Paginate[T any](page *Page[T]) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if page.CurrentPage <= 0 {
			page.CurrentPage = 0
		}
		switch {
		case page.PageSize > 100:
			page.PageSize = 100
		case page.PageSize <= 0:
			page.PageSize = 10
		}
		page.Pages = page.Total / page.PageSize
		if page.Total%page.PageSize != 0 {
			page.Pages++
		}
		p := page.CurrentPage
		if page.CurrentPage > page.Pages {
			p = page.Pages
		}
		size := page.PageSize
		offset := int((p - 1) * size)
		return db.Offset(offset).Limit(int(size))
	}
}

mysql.go

package database

import (
	// 导入gorm工具包

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var DB *gorm.DB

func Close() {
	db, _ := DB.DB()
	db.Close()
}

func InitMysql() error {
	dsn := "root:fuck@you@tcp(127.0.0.1:3306)/world?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})

	if err != nil {
		return err
	}
	DB = db
	return nil
}

DEMO:
city.go

package model

import (
	"gorm_page_generic/database"
)

type CityQueryInfo struct {
	PageInfo
	CountryCode string `json:"countryCode"`
	District    string `json:"district"`
}

type City struct {
	ID          int    `json:"id"`
	Name        string `json:"name"`
	CountryCode string `json:"countryCode"`
	District    string `json:"district"`
	Population  int    `json:"population"`
}

func (c *City) TableName() string {
	return "city"
}

func (c *City) SelectPageList(p *database.Page[City], wrapper map[string]interface{}) error {
	return p.SelectPage(wrapper)
}

调用使用

type CityService struct{}

var cityModel model.City

// 使用泛型调用分页查询
func (c *CityService) SelectPageList(queryVo model.CityQueryInfo) (*model.PageResponse[model.City], error) {
	p := &database.Page[model.City]{
		CurrentPage: queryVo.CurrentPage,
		PageSize:    queryVo.PageSize,
	}
	wrapper := make(map[string]interface{}, 0)
	if queryVo.CountryCode != "" {
		wrapper["CountryCode"] = queryVo.CountryCode
	}
	if queryVo.District != "" {
		wrapper["District"] = queryVo.District
	}
	err := cityModel.SelectPageList(p, wrapper)
	if err != nil {
		return nil, err
	}
	pageResponse := model.NewPageResponse(p)
	return pageResponse, err
}