release: v1.2.0 版本号提升 + 脚手架对齐 + 文档核验
- 版本号 1.1.1 → 1.2.0:app.go Version 常量;脚手架 GoMod 模板经 xlgo.Version 自动跟随;GUIDE 文档版本同步
- CHANGELOG/README 新增 v1.2.0 破坏性版本条目(包级全局 atomic.Pointer 治理、jwt.DefaultJWT 删除、FindWhereOrdered 签名变更、response 去 omitempty、cache.ErrRedisNotReady、config.Clone 深拷贝等)
- 脚手架对齐:RepositoryMake 模板 FindByName 改用 FindOne(走 readConn 读写分离,避免 M-35 GetDB 不路由 footgun)
- 文档核验修复(README/GUIDE 逐行对照源码 6595e94):
- README DB 示例 users := ...Find(&users) 自引用声明编译错误
- GUIDE xlgo.StartServer(engine,8080) 不存在 → engine.Run(":8080")
- GUIDE app.token_expire 死键(v1.1.0 已移除 AppConfig.TokenExpire)
- GUIDE jwt.expire: 86400 类型错(time.Duration 需字符串 "24h")
- GUIDE storage.Init(&cfg.Storage) 吞错误 → 显式 err 处理
- GUIDE 登录示例 token,_:=jwt.GenerateToken 吞错误 + time.Duration(cfg.JWT.Expire)*time.Second 双重转换
- GUIDE 验证规则表补 phone_strict / username
- .gitignore 忽略 8 个评审报告文件(仅本地保留,不入库;已从未推送提交中 filter-branch 清除)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,3 +7,11 @@ gitHub_release_*.md
|
||||
# 构建产物
|
||||
*.exe
|
||||
bin/
|
||||
claude_check_report_framework.md
|
||||
claude_check_report_module.md
|
||||
cross_review_assessment.md
|
||||
deepseek_check_report_framework.md
|
||||
deepseek_check_report_module.md
|
||||
glm_check_report_framework.md
|
||||
glm_check_report_modelue.md
|
||||
last_report.md
|
||||
|
||||
+8
-3
@@ -16,8 +16,12 @@ xlgo 框架更新日志。本文档遵循 [Keep a Changelog](https://keepachange
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
> 框架整体评估后的结构性修复,包含 2 CRITICAL + 12 HIGH + 6 MEDIUM 问题的修复。
|
||||
> 项目处于初级阶段,无下游用户,放心引入破坏性变更。
|
||||
_暂无未发布变更。_
|
||||
|
||||
## [1.2.0] - 2026-07-04
|
||||
|
||||
> 框架整体评估后的结构性修复:4 轮对抗性评审(deepseek / GLM / Claude / 终审)收口的全部 CRITICAL/HIGH/MEDIUM 问题 + 主线A 包级可变全局并发治理统一。
|
||||
> 项目处于初级阶段,无下游用户,放心引入破坏性变更。`go vet` + `go build` + `go test -race ./...` 全绿。
|
||||
|
||||
### Breaking ⚠️
|
||||
|
||||
@@ -964,7 +968,8 @@ v1.0.2 引入可插拔方言注册表后,`gorm.io/driver/postgres` 成为直
|
||||
- 基础框架功能
|
||||
- 完整示例代码
|
||||
|
||||
[Unreleased]: https://github.com/EthanCodeCraft/xlgo-core/compare/v1.1.1...HEAD
|
||||
[Unreleased]: https://github.com/EthanCodeCraft/xlgo-core/compare/v1.2.0...HEAD
|
||||
[1.2.0]: https://github.com/EthanCodeCraft/xlgo-core/compare/v1.1.1...v1.2.0
|
||||
[1.1.1]: https://github.com/EthanCodeCraft/xlgo-core/releases/tag/v1.1.1
|
||||
[1.1.0]: https://github.com/EthanCodeCraft/xlgo-core/releases/tag/v1.1.0
|
||||
[1.0.4]: https://github.com/EthanCodeCraft/xlgo-core/releases/tag/v1.0.4
|
||||
|
||||
@@ -111,7 +111,6 @@ app:
|
||||
env: "dev" # dev/test/prod
|
||||
debug: true
|
||||
base_url: "http://localhost:8080"
|
||||
token_expire: 86400 # Token过期时间(秒)
|
||||
|
||||
server:
|
||||
port: 8080
|
||||
@@ -134,7 +133,7 @@ redis:
|
||||
|
||||
jwt:
|
||||
secret: your_jwt_secret_key
|
||||
expire: 86400
|
||||
expire: "24h" # time.Duration,如 "24h"/"30m"
|
||||
|
||||
log:
|
||||
dir: ./logs
|
||||
@@ -701,7 +700,9 @@ if !ok {
|
||||
| `max=20` | 最大长度 |
|
||||
| `email` | 邮箱格式 |
|
||||
| `phone` | 手机号格式 |
|
||||
| `phone_strict` | 手机号严格校验(验证运营商号段) |
|
||||
| `password` | 密码强度(8-72 字节,需含大写+小写+数字) |
|
||||
| `username` | 字母开头,3-20 位字母/数字/下划线 |
|
||||
| `url` | URL 格式 |
|
||||
| `ip` | IP 地址格式 |
|
||||
|
||||
@@ -1070,7 +1071,8 @@ router.RegisterVersion(router.NewVersion("v1", "/api/v1"))
|
||||
// 应用路由
|
||||
router.Apply()
|
||||
|
||||
xlgo.StartServer(engine, 8080)
|
||||
// 启动服务(如需优雅关闭与生命周期管理,改用 app := xlgo.New(...); app.Run())
|
||||
engine.Run(":8080")
|
||||
```
|
||||
|
||||
#### 8.4.7 默认路由
|
||||
@@ -1199,7 +1201,9 @@ storage:
|
||||
import "github.com/EthanCodeCraft/xlgo-core/storage"
|
||||
|
||||
// 初始化
|
||||
storage.Init(&cfg.Storage)
|
||||
if err := storage.Init(&cfg.Storage); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 上传文件(从请求中获取)
|
||||
file, _ := c.FormFile("file")
|
||||
@@ -1799,13 +1803,17 @@ func Login(c *gin.Context) {
|
||||
}
|
||||
|
||||
// 生成Token
|
||||
token, _ := jwt.GenerateToken(user.ID, user.Username, "admin", "admin")
|
||||
token, err := jwt.GenerateToken(user.ID, user.Username, "admin", "admin")
|
||||
if err != nil {
|
||||
response.FailWithError(c, response.ErrServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// 缓存用户信息
|
||||
cache.GetCache().Set(c.Request.Context(),
|
||||
cache.KSession(token),
|
||||
user,
|
||||
time.Duration(cfg.JWT.Expire)*time.Second)
|
||||
cfg.JWT.Expire)
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"token": token,
|
||||
@@ -1817,5 +1825,5 @@ func Login(c *gin.Context) {
|
||||
|
||||
---
|
||||
|
||||
_文档版本: v1.1.1_
|
||||
_最后更新: 2026-07-03_
|
||||
_文档版本: v1.2.0_
|
||||
_最后更新: 2026-07-04_
|
||||
|
||||
@@ -246,7 +246,8 @@ database.InitDBWithReplicas(cfg, []string{
|
||||
})
|
||||
|
||||
// 读操作自动路由到从库
|
||||
users := database.GetReadDB().Find(&users)
|
||||
var users []model.User
|
||||
database.GetReadDB().Find(&users)
|
||||
|
||||
// 强制使用主库
|
||||
ctx := database.UseMaster(context.Background())
|
||||
@@ -819,6 +820,22 @@ docker run -d -p 8080:8080 xlgo-app:latest
|
||||
|
||||
> 完整变更历史见 [CHANGELOG.md](./CHANGELOG.md)。
|
||||
|
||||
### v1.2.0 (2026-07-04)
|
||||
|
||||
> **破坏性版本**:4 轮对抗性评审(deepseek / GLM / Claude / 终审)收口的全部 CRITICAL/HIGH/MEDIUM 修复 + 主线A 包级可变全局并发治理统一。`go vet` + `go build` + `go test -race ./...` 全绿。完整变更见 [CHANGELOG.md](./CHANGELOG.md)。
|
||||
|
||||
主要破坏性变更(升级前必读):
|
||||
|
||||
- **包级可变全局一律 `atomic.Pointer`**(主线A):`database.DefaultRedis`/`database.DefaultManager`/`storage.DefaultStorage`/`validation.Validator` 由裸指针改为 `atomic.Pointer[T]`。直接读字段调方法需改用 facade(`InitRedis`/`GetDB`/`ValidateStruct` 等)或 `.Load()`;`database.DefaultManager = x` 改 `database.SetDefaultManager(x)`。
|
||||
- **`jwt.DefaultJWT` 包级变量删除** → `GetDefaultJWT()` / `SetDefaultJWTManager()`。
|
||||
- **`repository.FindWhereOrdered`/`FindPageWhereOrdered` 签名**:`args []any` → `args ...any`,`order` 前置于 `query`。
|
||||
- **`response.Response` 的 `Data`/`RequestID` 去 `omitempty`**:两字段在所有响应中恒存在。
|
||||
- **`cache.IsLocked`/`GetLockTTL`/`ForceUnlock`** Redis 不可用改返 `ErrRedisNotReady`(锁操作正确性相关)。
|
||||
- **`config.Load()` 返回深拷贝**:新增 `(*Config).Clone()`;`Get()` 仍返只读指针(热路径零分配)。
|
||||
- **`handler.GetPage` 加 `page` 上限 10000**;`utils.EqualsIgnoreCase` 改 `strings.EqualFold`;`utils.ReadFile` 去 TOCTOU 前置检查(错误改 `errors.Is(err, os.ErrNotExist)`)。
|
||||
|
||||
升级:`go get github.com/EthanCodeCraft/xlgo-core@v1.2.0`(⚠️ 含破坏性变更,详见 CHANGELOG 迁移说明)
|
||||
|
||||
### v1.1.1 (2026-06-23)
|
||||
|
||||
> v1.1.0 的补丁发布:补 `ServerConfig.Host` 绑定地址、面向用户文案统一中文、修正 README 过时/错误描述(含会致启动失败的配置示例)。
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
// Version 框架版本号。发版时只改这一处,避免版本字面量散落各处。
|
||||
// CLI(xlgo version)、脚手架生成的 go.mod 等均引用此常量。
|
||||
const Version = "1.1.1"
|
||||
const Version = "1.2.0"
|
||||
|
||||
// HealthCheckFunc 健康检查函数
|
||||
type HealthCheckFunc func(context.Context) error
|
||||
|
||||
@@ -281,7 +281,7 @@ func createRepository(name, nameTitle string) error {
|
||||
content := fmt.Sprintf(templates.RepositoryMake,
|
||||
nameTitle, name, nameTitle, nameTitle,
|
||||
nameTitle, name, nameTitle, nameTitle, nameTitle, nameTitle,
|
||||
nameTitle, nameTitle, nameTitle,
|
||||
nameTitle, nameTitle,
|
||||
)
|
||||
content = replaceModuleImports(content)
|
||||
|
||||
|
||||
@@ -491,14 +491,13 @@ func New%sRepository() *%sRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// FindByName 根据名称查询
|
||||
// FindByName 根据名称查询。
|
||||
//
|
||||
// 走 BaseRepo.FindOne → readConn 读连接:默认路由到从库(读写分离,H6c),
|
||||
// 需读主库用 database.UseMaster(ctx),事务内自动 join 外层事务。
|
||||
// 不要用 r.GetDB() 自行查询——它返回注入的主库且不参与路由(M-35 footgun)。
|
||||
func (r *%sRepository) FindByName(ctx context.Context, name string) (*model.%s, error) {
|
||||
var m model.%s
|
||||
err := r.GetDB().WithContext(ctx).Where("name = ?", name).First(&m).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &m, nil
|
||||
return r.FindOne(ctx, "name = ?", name)
|
||||
}
|
||||
`,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user