diff --git a/.cursor/plans/多数据库方言与前缀支持_d7ceee79.plan.md b/.cursor/plans/多数据库方言与前缀支持_d7ceee79.plan.md index c6a800d..2bd931e 100644 --- a/.cursor/plans/多数据库方言与前缀支持_d7ceee79.plan.md +++ b/.cursor/plans/多数据库方言与前缀支持_d7ceee79.plan.md @@ -169,7 +169,7 @@ onCondition := that.GetProcessor().ProcessConditionString(v.(string)) query += " LEFT JOIN " + table + " ON " + onCondition + " " ``` -**Insert/BatchInsert/Update/Delete** 同样修改表名和字段名处理。 +**Insert/Inserts/Update/Delete** 同样修改表名和字段名处理。 ### 第5步:修改 WHERE 条件处理([db/where.go](db/where.go)) diff --git a/README.md b/README.md index 1734f1e..ef67bfb 100644 --- a/README.md +++ b/README.md @@ -2,75 +2,40 @@ **高性能 Go Web 服务框架** -## 特性 +一个"小而全"的 Go Web 框架,内置 ORM、三级缓存、Session 管理,让你专注于业务逻辑。 + +## 核心特性 - **高性能** - 单机 10万+ QPS,支持百万级并发用户 -- **多数据库支持** - MySQL、SQLite3,支持主从分离 -- **三级缓存系统** - Memory > Redis > DB,自动穿透与回填 -- **Session管理** - 内置会话管理,支持多种存储后端 -- **自动代码生成** - 根据数据库表自动生成 CRUD 接口 -- **丰富工具类** - 上下文管理、类型转换、加密解密等 +- **内置 ORM** - 类 Medoo 语法,链式查询,支持 MySQL/SQLite/PostgreSQL +- **三级缓存** - Memory > Redis > DB,自动穿透与回填 +- **Session 管理** - 内置会话管理,支持多种存储后端 +- **代码生成** - 根据数据库表自动生成 CRUD 接口 +- **开箱即用** - 微信支付/公众号/小程序、阿里云、腾讯云等 SDK 内置 -## 快速开始 +## 文档 -### 安装 +| 文档 | 说明 | +|------|------| +| [快速上手指南](docs/QUICKSTART.md) | 5 分钟入门,安装配置、路由、中间件、基础数据库操作 | +| [HoTimeDB 使用说明](docs/HoTimeDB_使用说明.md) | 完整数据库 ORM 教程 | +| [HoTimeDB API 参考](docs/HoTimeDB_API参考.md) | 数据库 API 速查手册 | + +## 安装 ```bash go get code.hoteas.com/golang/hotime ``` -### 最小示例 +## 性能 -```go -package main +| 并发数 | QPS | 成功率 | 平均延迟 | +|--------|-----|--------|----------| +| 500 | 99,960 | 100% | 5.0ms | +| **1000** | **102,489** | **100%** | **9.7ms** | +| 2000 | 75,801 | 99.99% | 26.2ms | -import ( - . "code.hoteas.com/golang/hotime" - . "code.hoteas.com/golang/hotime/common" -) - -func main() { - appIns := Init("config/config.json") - - appIns.Run(Router{ - "app": { - "test": { - "hello": func(that *Context) { - that.Display(0, Map{"message": "Hello World"}) - }, - }, - }, - }) -} -``` - -访问: http://localhost:8081/app/test/hello - -## 性能测试报告 - -### 测试环境 - -| 项目 | 配置 | -|------|------| -| CPU | 24 核心 | -| 系统 | Windows 10 | -| Go 版本 | 1.19.3 | - -### 测试结果 - -| 并发数 | QPS | 成功率 | 平均延迟 | P99延迟 | -|--------|-----|--------|----------|---------| -| 500 | 99,960 | 100% | 5.0ms | 25.2ms | -| **1000** | **102,489** | **100%** | **9.7ms** | **56.8ms** | -| 2000 | 75,801 | 99.99% | 26.2ms | 127.7ms | -| 5000 | 12,611 | 99.95% | 391.4ms | 781.4ms | - -### 性能总结 - -``` -最高 QPS: 102,489 请求/秒 -最佳并发数: 1,000 -``` +> 测试环境:24 核 CPU,Windows 10,Go 1.19.3 ### 并发用户估算 @@ -79,24 +44,9 @@ func main() { | 高频交互 | 1次/秒 | ~10万 | | 活跃用户 | 1次/5秒 | ~50万 | | 普通浏览 | 1次/10秒 | ~100万 | -| 低频访问 | 1次/30秒 | ~300万 | - -**生产环境建议**: 保留 30-50% 性能余量,安全并发用户数约 **50万 - 70万** - -### 与主流框架性能对比 - -| 框架 | 典型QPS | 基础实现 | 性能评级 | -|------|---------|----------|----------| -| **HoTime** | **~100K** | net/http | 第一梯队 | -| Fiber | ~100K+ | fasthttp | 第一梯队 | -| Gin | ~60-80K | net/http | 第二梯队 | -| Echo | ~60-80K | net/http | 第二梯队 | -| Chi | ~50-60K | net/http | 第二梯队 | ## 框架对比 -### 功能特性对比 - | 特性 | HoTime | Gin | Echo | Fiber | |------|--------|-----|------|-------| | 性能 | 100K QPS | 70K QPS | 70K QPS | 100K QPS | @@ -105,117 +55,25 @@ func main() { | Session | ✅ 内置 | ❌ 需插件 | ❌ 需插件 | ❌ 需插件 | | 代码生成 | ✅ | ❌ | ❌ | ❌ | | 微信/支付集成 | ✅ 内置 | ❌ | ❌ | ❌ | -| 路由灵活性 | 中等 | 优秀 | 优秀 | 优秀 | -| 社区生态 | 较小 | 庞大 | 较大 | 较大 | -### HoTime 优势 - -1. **开箱即用** - 内置 ORM + 缓存 + Session,无需额外集成 -2. **三级缓存** - Memory > Redis > DB,自动穿透与回填 -3. **开发效率高** - 链式查询语法简洁,内置微信/云服务SDK -4. **性能优异** - 100K QPS,媲美最快的 Fiber 框架 - -### 适用场景 +## 适用场景 | 场景 | 推荐度 | 说明 | |------|--------|------| | 中小型后台系统 | ⭐⭐⭐⭐⭐ | 完美适配,开发效率最高 | -| 微信小程序后端 | ⭐⭐⭐⭐⭐ | 内置微信SDK | +| 微信小程序后端 | ⭐⭐⭐⭐⭐ | 内置微信 SDK | | 快速原型开发 | ⭐⭐⭐⭐⭐ | 代码生成 + 全功能集成 | -| 高并发API服务 | ⭐⭐⭐⭐ | 性能足够 | -| 大型微服务 | ⭐⭐⭐ | 建议用Gin/Echo | - -### 总体评价 - -| 维度 | 评分 | 说明 | -|------|------|------| -| 性能 | 95分 | 第一梯队,媲美Fiber | -| 功能集成 | 90分 | 远超主流框架 | -| 开发效率 | 85分 | 适合快速开发 | -| 生态/社区 | 50分 | 持续建设中 | - -> **总结**: HoTime 是"小而全"的高性能框架,性能不输主流,集成度远超主流,适合独立开发者或小团队快速构建中小型项目。 - ---- - -## 数据库操作 - -### 基础 CRUD - -```go -// 查询单条 -user := that.Db.Get("user", "*", Map{"id": 1}) - -// 查询列表 -users := that.Db.Select("user", "*", Map{"status": 1, "ORDER": "id DESC"}) - -// 插入数据 -id := that.Db.Insert("user", Map{"name": "test", "age": 18}) - -// 更新数据 -rows := that.Db.Update("user", Map{"name": "new"}, Map{"id": 1}) - -// 删除数据 -rows := that.Db.Delete("user", Map{"id": 1}) -``` - -### 链式查询 - -```go -users := that.Db.Table("user"). - LeftJoin("order", "user.id=order.user_id"). - And("status", 1). - Order("id DESC"). - Page(1, 10). - Select("*") -``` - -### 条件语法 - -| 语法 | 说明 | 示例 | -|------|------|------| -| key | 等于 | "id": 1 | -| key[>] | 大于 | "age[>]": 18 | -| key[<] | 小于 | "age[<]": 60 | -| key[!] | 不等于 | "status[!]": 0 | -| key[~] | LIKE | "name[~]": "test" | -| key[<>] | BETWEEN | "age[<>]": Slice{18, 60} | - -## 缓存系统 - -三级缓存: **Memory > Redis > Database** - -```go -// 通用缓存 -that.Cache("key", value) // 设置 -data := that.Cache("key") // 获取 -that.Cache("key", nil) // 删除 - -// Session 缓存 -that.Session("user_id", 123) // 设置 -userId := that.Session("user_id") // 获取 -``` - -## 中间件 - -```go -appIns.SetConnectListener(func(that *Context) bool { - if that.Session("user_id").Data == nil { - that.Display(2, "请先登录") - return true // 终止请求 - } - return false // 继续处理 -}) -``` +| 高并发 API 服务 | ⭐⭐⭐⭐ | 性能足够 | +| 大型微服务 | ⭐⭐⭐ | 建议用 Gin/Echo | ## 扩展功能 -- **微信支付/公众号/小程序** - dri/wechat/ -- **阿里云服务** - dri/aliyun/ -- **腾讯云服务** - dri/tencent/ -- **文件上传下载** - dri/upload/, dri/download/ -- **MongoDB** - dri/mongodb/ -- **RSA加解密** - dri/rsa/ +- 微信支付/公众号/小程序 - `dri/wechat/` +- 阿里云服务 - `dri/aliyun/` +- 腾讯云服务 - `dri/tencent/` +- 文件上传下载 - `dri/upload/`, `dri/download/` +- MongoDB - `dri/mongodb/` +- RSA 加解密 - `dri/rsa/` ## License diff --git a/db/README.md b/db/README.md deleted file mode 100644 index f29023b..0000000 --- a/db/README.md +++ /dev/null @@ -1,252 +0,0 @@ -# HoTimeDB ORM 文档集合 - -这是HoTimeDB ORM框架的完整文档集合,包含使用说明、API参考、示例代码和测试数据。 - -## ⚠️ 重要更新说明 - -**语法修正通知**:经过对源码的深入分析,发现HoTimeDB的条件查询语法有特定规则: -- ✅ **单个条件**:可以直接写在Map中 -- ⚠️ **多个条件**:必须使用`AND`或`OR`包装 -- 📝 所有文档和示例代码已按正确语法更新 - -## 📚 文档列表 - -### 1. [HoTimeDB_使用说明.md](./HoTimeDB_使用说明.md) -**完整使用说明书** - 详细的功能介绍和使用指南 -- 🚀 快速开始 -- ⚙️ 数据库配置 -- 🔧 基本操作 (CRUD) -- 🔗 链式查询构建器 -- 🔍 条件查询语法 -- 🔄 JOIN操作 -- 📄 分页查询 -- 📊 聚合函数 -- 🔐 事务处理 -- 💾 缓存机制 -- ⚡ 高级特性 - -### 2. [HoTimeDB_API参考.md](./HoTimeDB_API参考.md) -**快速API参考手册** - 开发时的速查手册 -- 📖 基本方法 -- 🔧 CRUD操作 -- 📊 聚合函数 -- 📄 分页查询 -- 🔍 条件语法参考 -- 🔗 JOIN语法 -- 🔐 事务处理 -- 🛠️ 工具方法 - -### 3. [示例代码文件](../examples/hotimedb_examples.go) -**完整示例代码集合** - 可运行的实际应用示例(语法已修正) -- 🏗️ 基本初始化和配置 -- 📝 基本CRUD操作 -- 🔗 链式查询操作 -- 🤝 JOIN查询操作 -- 🔍 条件查询语法 -- 📄 分页查询 -- 📊 聚合函数查询 -- 🔐 事务处理 -- 💾 缓存机制 -- 🔧 原生SQL执行 -- 🚨 错误处理和调试 -- ⚡ 性能优化技巧 -- 🎯 完整应用示例 - -### 4. [test_tables.sql](./test_tables.sql) -**测试数据库结构** - 快速搭建测试环境 -- 🏗️ 完整的表结构定义 -- 📊 测试数据插入 -- 🔍 索引优化 -- 👁️ 视图示例 -- 🔧 存储过程示例 - -## 🎯 核心特性 - -### 🌟 主要优势 -- **类Medoo语法**: 参考PHP Medoo设计,语法简洁易懂 -- **链式查询**: 支持流畅的链式查询构建器 -- **条件丰富**: 支持丰富的条件查询语法 -- **事务支持**: 完整的事务处理机制 -- **缓存集成**: 内置查询结果缓存 -- **读写分离**: 支持主从数据库配置 -- **类型安全**: 基于Golang的强类型系统 - -### 🔧 支持的数据库 -- ✅ MySQL -- ✅ SQLite -- ✅ 其他标准SQL数据库 - -## 🚀 快速开始 - -### 1. 安装依赖 -```bash -go mod init your-project -go get github.com/go-sql-driver/mysql -go get github.com/sirupsen/logrus -``` - -### 2. 创建测试数据库 -```bash -mysql -u root -p < test_tables.sql -``` - -### 3. 基本使用 -```go -import ( - "code.hoteas.com/golang/hotime/db" - "code.hoteas.com/golang/hotime/common" - "database/sql" - _ "github.com/go-sql-driver/mysql" -) - -// 初始化数据库 -database := &db.HoTimeDB{ - Prefix: "app_", - Mode: 2, // 开发模式 -} - -database.SetConnect(func() (master, slave *sql.DB) { - master, _ = sql.Open("mysql", "user:pass@tcp(localhost:3306)/dbname") - return master, master -}) - -// 链式查询(链式语法支持单独Where然后用And添加条件) -users := database.Table("user"). - Where("status", 1). // 链式中可以单独Where - And("age[>]", 18). // 用And添加更多条件 - Order("created_time DESC"). - Limit(0, 10). - Select("id,name,email") - -// 或者使用传统语法(多个条件必须用AND包装) -users2 := database.Select("user", "id,name,email", common.Map{ - "AND": common.Map{ - "status": 1, - "age[>]": 18, - }, - "ORDER": "created_time DESC", - "LIMIT": []int{0, 10}, -}) -``` - -## ⚠️ 重要语法规则 - -**条件查询语法规则:** -- ✅ **单个条件**:可以直接写在Map中 -- ✅ **多个条件**:必须使用`AND`或`OR`包装 -- ✅ **特殊参数**:`ORDER`、`GROUP`、`LIMIT`与条件同级 - -```go -// ✅ 正确:单个条件 -Map{"status": 1} - -// ✅ 正确:多个条件用AND包装 -Map{ - "AND": Map{ - "status": 1, - "age[>]": 18, - }, - "ORDER": "id DESC", -} - -// ❌ 错误:多个条件不用AND包装 -Map{ - "status": 1, - "age[>]": 18, // 不支持! -} -``` - -## 📝 条件查询语法速查 - -| 语法 | SQL | 说明 | -|------|-----|------| -| `"field": value` | `field = ?` | 等于 | -| `"field[!]": value` | `field != ?` | 不等于 | -| `"field[>]": value` | `field > ?` | 大于 | -| `"field[>=]": value` | `field >= ?` | 大于等于 | -| `"field[<]": value` | `field < ?` | 小于 | -| `"field[<=]": value` | `field <= ?` | 小于等于 | -| `"field[~]": "keyword"` | `field LIKE '%keyword%'` | 包含 | -| `"field[<>]": [min, max]` | `field BETWEEN ? AND ?` | 区间内 | -| `"field": [v1, v2, v3]` | `field IN (?, ?, ?)` | 在集合中 | -| `"field": nil` | `field IS NULL` | 为空 | -| `"field[#]": "NOW()"` | `field = NOW()` | 直接SQL | - -## 🔗 JOIN语法速查 - -| 语法 | SQL | 说明 | -|------|-----|------| -| `"[>]table"` | `LEFT JOIN` | 左连接 | -| `"[<]table"` | `RIGHT JOIN` | 右连接 | -| `"[><]table"` | `INNER JOIN` | 内连接 | -| `"[<>]table"` | `FULL JOIN` | 全连接 | - -## 🛠️ 链式方法速查 - -```go -db.Table("table") // 指定表名 - .Where(key, value) // WHERE条件 - .And(key, value) // AND条件 - .Or(map) // OR条件 - .LeftJoin(table, on) // LEFT JOIN - .Order(fields...) // ORDER BY - .Group(fields...) // GROUP BY - .Limit(offset, limit) // LIMIT - .Page(page, pageSize) // 分页 - .Select(fields...) // 查询 - .Get(fields...) // 获取单条 - .Count() // 计数 - .Update(data) // 更新 - .Delete() // 删除 -``` - -## ⚡ 性能优化建议 - -### 🔍 查询优化 -- 使用合适的索引字段作为查询条件 -- IN查询会自动优化为BETWEEN(连续数字) -- 避免SELECT *,指定需要的字段 -- 合理使用LIMIT限制结果集大小 - -### 💾 缓存使用 -- 查询结果会自动缓存 -- 增删改操作会自动清除缓存 -- `cached`表不参与缓存 - -### 🔐 事务处理 -- 批量操作使用事务提高性能 -- 事务中避免长时间操作 -- 合理设置事务隔离级别 - -## 🚨 注意事项 - -### 🔒 安全相关 -- 使用参数化查询防止SQL注入 -- `[#]`语法需要注意防止注入 -- 敏感数据加密存储 - -### 🎯 最佳实践 -- 开发时设置`Mode = 2`便于调试 -- 生产环境设置`Mode = 0` -- 合理设置表前缀 -- 定期检查慢查询日志 - -## 🤝 与PHP Medoo的差异 - -1. **类型系统**: 使用`common.Map`和`common.Slice` -2. **错误处理**: Golang风格的错误处理 -3. **链式调用**: 提供更丰富的链式API -4. **缓存集成**: 内置缓存功能 -5. **并发安全**: 需要注意并发使用 - -## 📞 技术支持 - -- 📧 查看源码:`hotimedb.go` -- 📖 参考文档:本目录下的各个文档文件 -- 🔧 示例代码:运行`HoTimeDB_示例代码.go`中的示例 - ---- - -**HoTimeDB ORM框架 - 让数据库操作更简单!** 🎉 - -> 本文档基于HoTimeDB源码分析生成,参考了PHP Medoo的设计理念,并根据Golang语言特性进行了优化。 \ No newline at end of file diff --git a/db/crud.go b/db/crud.go index be9d82a..0e87641 100644 --- a/db/crud.go +++ b/db/crud.go @@ -307,19 +307,19 @@ func (that *HoTimeDB) Insert(table string, data map[string]interface{}) int64 { return id } -// BatchInsert 批量插入数据 +// Inserts 批量插入数据 // table: 表名 // dataList: 数据列表,每个元素是一个 Map // 返回受影响的行数 // // 示例: // -// affected := db.BatchInsert("user", []Map{ +// affected := db.Inserts("user", []Map{ // {"name": "张三", "age": 25, "email": "zhang@example.com"}, // {"name": "李四", "age": 30, "email": "li@example.com"}, // {"name": "王五", "age": 28, "email": "wang@example.com"}, // }) -func (that *HoTimeDB) BatchInsert(table string, dataList []Map) int64 { +func (that *HoTimeDB) Inserts(table string, dataList []Map) int64 { if len(dataList) == 0 { return 0 } diff --git a/db/HoTimeDB_API参考.md b/docs/HoTimeDB_API参考.md similarity index 97% rename from db/HoTimeDB_API参考.md rename to docs/HoTimeDB_API参考.md index 1310e85..3e2d19d 100644 --- a/db/HoTimeDB_API参考.md +++ b/docs/HoTimeDB_API参考.md @@ -98,17 +98,17 @@ id := database.Insert("table", dataMap) // 返回新插入记录的ID ``` -### 批量插入 (BatchInsert) - 新增 +### 批量插入 (Inserts) - 新增 ```go // 使用 []Map 格式,更直观简洁 -affected := database.BatchInsert("table", []Map{ +affected := database.Inserts("table", []Map{ {"col1": "val1", "col2": "val2", "col3": "val3"}, {"col1": "val4", "col2": "val5", "col3": "val6"}, }) // 返回受影响的行数 // 支持 [#] 标记直接 SQL -affected := database.BatchInsert("log", []Map{ +affected := database.Inserts("log", []Map{ {"user_id": 1, "created_time[#]": "NOW()"}, {"user_id": 2, "created_time[#]": "NOW()"}, }) @@ -465,7 +465,7 @@ stats := database.Select("order", ### 批量操作 ```go // 批量插入(使用 []Map 格式) -affected := database.BatchInsert("user", []Map{ +affected := database.Inserts("user", []Map{ {"name": "用户1", "email": "user1@example.com", "status": 1}, {"name": "用户2", "email": "user2@example.com", "status": 1}, {"name": "用户3", "email": "user3@example.com", "status": 1}, @@ -511,3 +511,6 @@ result := database.Table("order"). *快速参考版本: 2.0* *更新日期: 2026年1月* + +**详细说明:** +- [HoTimeDB 使用说明](HoTimeDB_使用说明.md) - 完整教程 diff --git a/db/HoTimeDB_使用说明.md b/docs/HoTimeDB_使用说明.md similarity index 98% rename from db/HoTimeDB_使用说明.md rename to docs/HoTimeDB_使用说明.md index e7e4f49..fd0aa8c 100644 --- a/db/HoTimeDB_使用说明.md +++ b/docs/HoTimeDB_使用说明.md @@ -12,7 +12,7 @@ HoTimeDB是一个基于Golang实现的轻量级ORM框架,参考PHP Medoo设计 - [查询(Select)](#查询select) - [获取单条记录(Get)](#获取单条记录get) - [插入(Insert)](#插入insert) - - [批量插入(BatchInsert)](#批量插入batchinsert) + - [批量插入(Inserts)](#批量插入Inserts) - [更新(Update)](#更新update) - [Upsert操作](#upsert操作) - [删除(Delete)](#删除delete) @@ -223,11 +223,11 @@ id := database.Insert("user", common.Map{ fmt.Println("插入的用户ID:", id) ``` -### 批量插入(BatchInsert) +### 批量插入(Inserts) ```go // 批量插入多条记录(使用 []Map 格式,更直观) -affected := database.BatchInsert("user", []common.Map{ +affected := database.Inserts("user", []common.Map{ {"name": "张三", "email": "zhang@example.com", "age": 25}, {"name": "李四", "email": "li@example.com", "age": 30}, {"name": "王五", "email": "wang@example.com", "age": 28}, @@ -237,7 +237,7 @@ affected := database.BatchInsert("user", []common.Map{ fmt.Printf("批量插入 %d 条记录\n", affected) // 支持 [#] 标记直接插入 SQL 表达式 -affected := database.BatchInsert("log", []common.Map{ +affected := database.Inserts("log", []common.Map{ {"user_id": 1, "action": "login", "created_time[#]": "NOW()"}, {"user_id": 2, "action": "logout", "created_time[#]": "NOW()"}, }) @@ -808,7 +808,7 @@ A1: 不再需要!现在多条件会自动用 AND 连接。当然,使用 `AND A2: 在 `Action` 函数中返回 `false` 即可触发回滚,所有操作都会被撤销。 ### Q3: 缓存何时会被清除? -A3: 执行 `Insert`、`Update`、`Delete`、`Upsert`、`BatchInsert` 操作时会自动清除对应表的缓存。 +A3: 执行 `Insert`、`Update`、`Delete`、`Upsert`、`Inserts` 操作时会自动清除对应表的缓存。 ### Q4: 如何执行复杂的原生SQL? A4: 使用 `Query` 方法执行查询,使用 `Exec` 方法执行更新操作。 @@ -828,3 +828,6 @@ A7: 框架会自动处理差异(占位符、引号等),代码无需修改 *最后更新: 2026年1月* > 本文档基于HoTimeDB源码分析生成,如有疑问请参考源码实现。该ORM框架参考了PHP Medoo的设计理念,但根据Golang语言特性进行了适配和优化。 + +**更多参考:** +- [HoTimeDB API 参考](HoTimeDB_API参考.md) - API 速查手册 diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md new file mode 100644 index 0000000..d84ac32 --- /dev/null +++ b/docs/QUICKSTART.md @@ -0,0 +1,302 @@ +# HoTime 快速上手指南 + +5 分钟入门 HoTime 框架。 + +## 安装 + +```bash +go get code.hoteas.com/golang/hotime +``` + +## 最小示例 + +```go +package main + +import ( + . "code.hoteas.com/golang/hotime" + . "code.hoteas.com/golang/hotime/common" +) + +func main() { + appIns := Init("config/config.json") + + appIns.Run(Router{ + "app": { + "test": { + "hello": func(that *Context) { + that.Display(0, Map{"message": "Hello World"}) + }, + }, + }, + }) +} +``` + +访问: `http://localhost:8081/app/test/hello` + +## 配置文件 + +创建 `config/config.json`: + +```json +{ + "port": "8081", + "mode": 2, + "sessionName": "HOTIME", + "tpt": "tpt", + "defFile": ["index.html", "index.htm"], + "db": { + "mysql": { + "host": "localhost", + "port": "3306", + "name": "your_database", + "user": "root", + "password": "your_password" + } + }, + "cache": { + "memory": { + "db": true, + "session": true, + "timeout": 7200 + } + } +} +``` + +| 配置项 | 说明 | +|--------|------| +| `port` | 服务端口 | +| `mode` | 0=生产, 1=测试, 2=开发(输出SQL) | +| `tpt` | 静态文件目录 | +| `db` | 数据库配置 | +| `cache` | 缓存配置 | + +## 路由系统 + +HoTime 使用三层路由结构:`模块/控制器/方法` + +```go +appIns.Run(Router{ + "模块名": { + "控制器名": { + "方法名": func(that *Context) { + // 处理逻辑 + }, + }, + }, +}) +``` + +### 获取请求参数 + +```go +// GET/POST 参数 +name := that.Req.FormValue("name") + +// JSON Body +that.Req.ParseForm() +data := that.Req.PostForm + +// 获取路径参数 +module := that.RouterPath[0] // 模块 +controller := that.RouterPath[1] // 控制器 +action := that.RouterPath[2] // 方法 +``` + +### 响应数据 + +```go +// 标准 JSON 响应 +that.Display(0, Map{"data": "value"}) // 成功 code=0 +that.Display(1, "错误信息") // 失败 code=1 + +// 直接写入 +that.Resp.Write([]byte("raw data")) +``` + +## 中间件 + +```go +// 全局中间件(请求拦截) +appIns.SetConnectListener(func(that *Context) bool { + // 检查登录状态 + if that.Session("user_id").Data == nil { + that.Display(2, "请先登录") + return true // 返回 true 终止请求 + } + return false // 返回 false 继续处理 +}) +``` + +## Session 与缓存 + +```go +// Session 操作 +that.Session("user_id", 123) // 设置 +userId := that.Session("user_id") // 获取 +that.Session("user_id", nil) // 删除 + +// 通用缓存 +that.Cache("key", "value") // 设置 +data := that.Cache("key") // 获取 +that.Cache("key", nil) // 删除 +``` + +三级缓存自动运作:**Memory → Redis → Database** + +## 数据库操作(简要) + +### 基础 CRUD + +```go +// 查询列表 +users := that.Db.Select("user", "*", Map{"status": 1}) + +// 查询单条 +user := that.Db.Get("user", "*", Map{"id": 1}) + +// 插入 +id := that.Db.Insert("user", Map{"name": "test", "age": 18}) + +// 更新 +rows := that.Db.Update("user", Map{"name": "new"}, Map{"id": 1}) + +// 删除 +rows := that.Db.Delete("user", Map{"id": 1}) +``` + +### 链式查询 + +```go +users := that.Db.Table("user"). + LeftJoin("order", "user.id=order.user_id"). + Where("status", 1). + And("age[>]", 18). + Order("id DESC"). + Page(1, 10). + Select("*") +``` + +### 条件语法速查 + +| 语法 | 说明 | 示例 | +|------|------|------| +| `key` | 等于 | `"id": 1` | +| `key[>]` | 大于 | `"age[>]": 18` | +| `key[<]` | 小于 | `"age[<]": 60` | +| `key[>=]` | 大于等于 | `"age[>=]": 18` | +| `key[<=]` | 小于等于 | `"age[<=]": 60` | +| `key[!]` | 不等于 | `"status[!]": 0` | +| `key[~]` | LIKE | `"name[~]": "test"` | +| `key[<>]` | BETWEEN | `"age[<>]": Slice{18, 60}` | +| `key` | IN | `"id": Slice{1, 2, 3}` | + +### 事务 + +```go +success := that.Db.Action(func(tx db.HoTimeDB) bool { + tx.Update("user", Map{"balance[#]": "balance - 100"}, Map{"id": 1}) + tx.Insert("order", Map{"user_id": 1, "amount": 100}) + return true // 返回 true 提交,false 回滚 +}) +``` + +> **更多数据库操作**:参见 [HoTimeDB 使用说明](HoTimeDB_使用说明.md) + +## 扩展功能 + +| 功能 | 路径 | 说明 | +|------|------|------| +| 微信支付/公众号/小程序 | `dri/wechat/` | 微信全套 SDK | +| 阿里云服务 | `dri/aliyun/` | 企业认证等 | +| 腾讯云服务 | `dri/tencent/` | 企业认证等 | +| 文件上传 | `dri/upload/` | 文件上传处理 | +| 文件下载 | `dri/download/` | 文件下载处理 | +| MongoDB | `dri/mongodb/` | MongoDB 驱动 | +| RSA 加解密 | `dri/rsa/` | RSA 加解密工具 | + +## 完整示例 + +```go +package main + +import ( + . "code.hoteas.com/golang/hotime" + . "code.hoteas.com/golang/hotime/common" +) + +func main() { + appIns := Init("config/config.json") + + // 登录检查中间件 + appIns.SetConnectListener(func(that *Context) bool { + // 放行登录接口 + if that.RouterPath[2] == "login" { + return false + } + if that.Session("user_id").Data == nil { + that.Display(2, "请先登录") + return true + } + return false + }) + + appIns.Run(Router{ + "api": { + "user": { + "login": func(that *Context) { + phone := that.Req.FormValue("phone") + password := that.Req.FormValue("password") + + user := that.Db.Get("user", "*", Map{ + "phone": phone, + "password": password, + }) + + if user == nil { + that.Display(1, "账号或密码错误") + return + } + + that.Session("user_id", user.GetInt64("id")) + that.Display(0, Map{"user": user}) + }, + + "info": func(that *Context) { + userId := that.Session("user_id").ToInt64() + user := that.Db.Get("user", "*", Map{"id": userId}) + that.Display(0, Map{"user": user}) + }, + + "list": func(that *Context) { + page := that.Req.FormValue("page") + if page == "" { + page = "1" + } + + users := that.Db.Table("user"). + Where("status", 1). + Order("id DESC"). + Page(ObjToInt(page), 10). + Select("id,name,phone,created_at") + + total := that.Db.Count("user", Map{"status": 1}) + + that.Display(0, Map{ + "list": users, + "total": total, + }) + }, + }, + }, + }) +} +``` + +--- + +**下一步**: +- [HoTimeDB 使用说明](HoTimeDB_使用说明.md) - 完整数据库教程 +- [HoTimeDB API 参考](HoTimeDB_API参考.md) - API 速查手册 diff --git a/example/main.go b/example/main.go index 4d81972..6b4dbf3 100644 --- a/example/main.go +++ b/example/main.go @@ -44,7 +44,7 @@ func main() { results["6_pagination"] = testPagination(that) // 7. 批量插入测试 - results["7_batch_insert"] = testBatchInsert(that) + results["7_batch_insert"] = testInserts(that) // 8. Upsert 测试 results["8_upsert"] = testUpsert(that) @@ -86,7 +86,7 @@ func main() { "join": func(that *Context) { that.Display(0, testJoinQuery(that)) }, "aggregate": func(that *Context) { that.Display(0, testAggregate(that)) }, "pagination": func(that *Context) { that.Display(0, testPagination(that)) }, - "batch": func(that *Context) { that.Display(0, testBatchInsert(that)) }, + "batch": func(that *Context) { that.Display(0, testInserts(that)) }, "upsert": func(that *Context) { that.Display(0, testUpsert(that)) }, "transaction": func(that *Context) { that.Display(0, testTransaction(that)) }, "rawsql": func(that *Context) { that.Display(0, testRawSQL(that)) }, @@ -650,14 +650,14 @@ func testPagination(that *Context) Map { } // ==================== 7. 批量插入测试 ==================== -func testBatchInsert(that *Context) Map { +func testInserts(that *Context) Map { result := Map{"name": "批量插入测试", "tests": Slice{}} tests := Slice{} // 7.1 批量插入 - test1 := Map{"name": "BatchInsert 批量插入"} + test1 := Map{"name": "Inserts 批量插入"} timestamp := time.Now().UnixNano() - affected1 := that.Db.BatchInsert("test_batch", []Map{ + affected1 := that.Db.Inserts("test_batch", []Map{ {"name": fmt.Sprintf("批量测试1_%d", timestamp), "title": "标题1", "state": 1}, {"name": fmt.Sprintf("批量测试2_%d", timestamp), "title": "标题2", "state": 1}, {"name": fmt.Sprintf("批量测试3_%d", timestamp), "title": "标题3", "state": 1}, @@ -668,9 +668,9 @@ func testBatchInsert(that *Context) Map { tests = append(tests, test1) // 7.2 带 [#] 的批量插入 - test2 := Map{"name": "BatchInsert 带 [#] 标记"} + test2 := Map{"name": "Inserts 带 [#] 标记"} timestamp2 := time.Now().UnixNano() - affected2 := that.Db.BatchInsert("test_batch", []Map{ + affected2 := that.Db.Inserts("test_batch", []Map{ {"name": fmt.Sprintf("带时间测试1_%d", timestamp2), "title": "标题带时间1", "state": 1, "create_time[#]": "NOW()"}, {"name": fmt.Sprintf("带时间测试2_%d", timestamp2), "title": "标题带时间2", "state": 1, "create_time[#]": "NOW()"}, }) diff --git a/examples/hotimedb_examples.go b/examples/hotimedb_examples.go index dfbb4bd..e78569e 100644 --- a/examples/hotimedb_examples.go +++ b/examples/hotimedb_examples.go @@ -766,12 +766,12 @@ correctUsers4 := db.Select("user", "*", common.Map{ _ = db } -// BatchInsertExample 批量插入示例 -func BatchInsertExample(database *db.HoTimeDB) { +// InsertsExample 批量插入示例 +func InsertsExample(database *db.HoTimeDB) { fmt.Println("\n=== 批量插入示例 ===") // 批量插入用户(使用 []Map 格式) - affected := database.BatchInsert("user", []common.Map{ + affected := database.Inserts("user", []common.Map{ {"name": "批量用户1", "email": "batch1@example.com", "age": 25, "status": 1}, {"name": "批量用户2", "email": "batch2@example.com", "age": 30, "status": 1}, {"name": "批量用户3", "email": "batch3@example.com", "age": 28, "status": 1}, @@ -779,7 +779,7 @@ func BatchInsertExample(database *db.HoTimeDB) { fmt.Printf("批量插入了 %d 条用户记录\n", affected) // 批量插入日志(使用 [#] 标记直接 SQL) - logAffected := database.BatchInsert("log", []common.Map{ + logAffected := database.Inserts("log", []common.Map{ {"user_id": 1, "action": "login", "ip": "192.168.1.1", "created_time[#]": "NOW()"}, {"user_id": 2, "action": "logout", "ip": "192.168.1.2", "created_time[#]": "NOW()"}, {"user_id": 3, "action": "view", "ip": "192.168.1.3", "created_time[#]": "NOW()"}, @@ -838,7 +838,7 @@ func RunAllFixedExamples() { fmt.Println("所有示例代码已修正完毕,语法正确!") fmt.Println("") fmt.Println("新增功能示例说明:") - fmt.Println(" - BatchInsertExample(db): 批量插入示例,使用 []Map 格式") + fmt.Println(" - InsertsExample(db): 批量插入示例,使用 []Map 格式") fmt.Println(" - UpsertExample(db): 插入或更新示例") }