优化方法的使用

This commit is contained in:
yun
2026-09-19 01:31:34 +08:00
parent 00eba5cc75
commit 407fc49e0c
20 changed files with 1710 additions and 376 deletions
Executable
+24
View File
@@ -0,0 +1,24 @@
module code.yun.ink/pkg/responsex/gormx
go 1.22.4
require (
github.com/glebarez/sqlite v1.11.0
gorm.io/gorm v1.30.0
)
require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/glebarez/go-sqlite v1.21.2 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.20.0 // indirect
modernc.org/libc v1.22.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.23.1 // indirect
)
Executable
+34
View File
@@ -0,0 +1,34 @@
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
Regular → Executable
+6
View File
@@ -1,8 +1,14 @@
// Package gormx 提供 responsex 的 GORM 分页辅助。
//
// 按需加载:只有显式 import 本包的项目才依赖 gorm。
//
// import 路径:code.yun.ink/pkg/responsex/gormx
package gormx
import "gorm.io/gorm"
// 计算GORM DB的分页
// page 与 size 同时小于等于 0 时,只限制最大条数(1000),不做偏移
func GetDbOffset(db *gorm.DB, page, size int64) *gorm.DB {
offset := int(0)
limit := int(0)
Regular → Executable
+38 -10
View File
@@ -1,6 +1,8 @@
package gormx_test
import (
"fmt"
"strings"
"testing"
"code.yun.ink/pkg/responsex/gormx"
@@ -18,19 +20,29 @@ func newDB(t *testing.T) *gorm.DB {
return db
}
// newDryRunDB 创建 DryRun 模式的 DB,用于断言生成的 SQL,不真正查询
func newDryRunDB(t *testing.T) *gorm.DB {
t.Helper()
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{DryRun: true})
if err != nil {
t.Fatalf("open sqlite failed: %v", err)
}
return db
}
func TestGetDbOffset(t *testing.T) {
tests := []struct {
name string
page, size int64
wantOffset int
wantLimit int
name string
page, size int64
wantOffset int
wantLimit int
}{
{"page1 size10", 1, 10, 0, 10},
{"page2 size10", 2, 10, 10, 10},
{"page3 size20", 3, 20, 40, 20},
{"page0 size10 default page to 1", 0, 10, 0, 10},
{"page1 size0 default size to 10", 1, 0, 0, 10},
{"both negative or zero max 1000", 0, 0, 0, 1000},
{"both zero max 1000", 0, 0, 0, 1000},
{"negative page default to 1", -1, 10, 0, 10},
{"negative size default to 10", 1, -1, 0, 10},
{"both negative", -1, -1, 0, 1000},
@@ -39,14 +51,28 @@ func TestGetDbOffset(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
db := newDB(t)
result := gormx.GetDbOffset(db, tt.page, tt.size)
db := newDryRunDB(t)
var m testModel
stmt := gormx.GetDbOffset(db, tt.page, tt.size).Find(&m).Statement
stmt := result.Statement
// 验证 Limit 被正确设置
if stmt == nil {
t.Fatal("statement is nil")
}
got := stmt.SQL.String()
if got == "" {
t.Fatal("no SQL generated")
}
// 断言生成的 SQL 片段,避免依赖 Vars 顺序
wantLimit := fmt.Sprintf("LIMIT %d", tt.wantLimit)
if tt.wantOffset > 0 {
wantOffset := fmt.Sprintf("OFFSET %d", tt.wantOffset)
if !strings.Contains(got, wantOffset) {
t.Errorf("sql %q 缺少 %q", got, wantOffset)
}
}
if !strings.Contains(got, wantLimit) {
t.Errorf("sql %q 缺少 %q", got, wantLimit)
}
})
}
}
@@ -54,7 +80,9 @@ func TestGetDbOffset(t *testing.T) {
func TestGetDbOffset_Chaining(t *testing.T) {
db := newDB(t)
db.AutoMigrate(&testModel{})
if err := db.AutoMigrate(&testModel{}); err != nil {
t.Fatalf("migrate failed: %v", err)
}
// 插入测试数据
for i := 1; i <= 50; i++ {