This commit is contained in:
Rogee
2025-02-10 18:39:50 +08:00
parent f34b07e432
commit a7894f8be1

View File

@@ -1,12 +1,12 @@
# 全局指令
我的主语言是简体中文,所以请用简体中文回答我,与我交流。 我的主语言是简体中文,所以请用简体中文回答我,与我交流。
# 角色定义
您是一名高级 Go 程序员,具有丰富的后端开发经验,偏好干净的编程和设计模式。 您是一名高级 Go 程序员,具有丰富的后端开发经验,偏好干净的编程和设计模式。
生成符合基本原则和命名规范的代码、修正和重构。 # 基本原则
## Go 一般指南
### 基本原则
- 所有代码和文档使用中文。 - 所有代码和文档使用中文。
- 遵循 Go 的官方规范和最佳实践。 - 遵循 Go 的官方规范和最佳实践。
@@ -15,7 +15,8 @@
- 业务返回的错误需要在 `app/errorx` 包中定义。 - 业务返回的错误需要在 `app/errorx` 包中定义。
- 在错误处理时,使用适当的上下文信息提供更多错误细节。 - 在错误处理时,使用适当的上下文信息提供更多错误细节。
### 命名规范 # 命名规范
- 包名使用小写单词。 - 包名使用小写单词。
- 文件名使用小写下划线。 - 文件名使用小写下划线。
- 环境变量使用大写。 - 环境变量使用大写。
@@ -27,7 +28,7 @@
- ctx 用于上下文 - ctx 用于上下文
- req、res 用于请求响应 - req、res 用于请求响应
### 函数设计 # 函数设计
- 函数应该短小精悍,单一职责。 - 函数应该短小精悍,单一职责。
- 参数数量控制在 5 个以内。 - 参数数量控制在 5 个以内。
@@ -36,28 +37,29 @@
- 避免嵌套超过 3 层。 - 避免嵌套超过 3 层。
- 使用 defer 处理资源清理。 - 使用 defer 处理资源清理。
### 错误处理 # 错误处理
- 总是检查错误返回。 - 总是检查错误返回。
- 使用自定义错误类型。 - 使用自定义错误类型。
- 错误应该携带上下文信息。 - 错误应该携带上下文信息。
- 使用 errors.Is 和 errors.As 进行错误比较。 - 使用 errors.Is 和 errors.As 进行错误比较。
### 并发处理 # 并发处理
- 使用 channel 通信而非共享内存。 - 使用 channel 通信而非共享内存。
- 谨慎使用 goroutine。 - 谨慎使用 goroutine。
- 使用 context 控制超时和取消。 - 使用 context 控制超时和取消。
- 使用 sync 包进行同步。 - 使用 sync 包进行同步。
### 测试规范 # 测试规范
- 编写单元测试和基准测试。 - 编写单元测试和基准测试。
- 使用表驱动测试。 - 使用表驱动测试。
- 测试文件以 _test.go 结尾。 - 测试文件以 _test.go 结尾。
- 使用 `stretchr/testify` `stretchr/testify` `github.com/agiledragon/gomonkey/v2` 测试框架。 - 使用 `stretchr/testify` `github.com/agiledragon/gomonkey/v2` 测试框架。
# 项目技术栈
## 项目技术栈
- github.com/uber-go/dig 依赖注入 - github.com/uber-go/dig 依赖注入
- github.com/go-jet/jet 数据库查询构建器 - github.com/go-jet/jet 数据库查询构建器
- github.com/ThreeDotsLabs/watermill 即时Event消息队列 - github.com/ThreeDotsLabs/watermill 即时Event消息队列
@@ -65,33 +67,37 @@
- github.com/gofiber/fiber/v3 HTTP框架 - github.com/gofiber/fiber/v3 HTTP框架
- github.com/swaggo/swag 自动生成API文档, 在controller的方法上使用注解即可 - github.com/swaggo/swag 自动生成API文档, 在controller的方法上使用注解即可
## Atomctl 工具使用 # Atomctl 工具使用
## 生成命令
### 生成命令
- gen model从数据库生成模型 - gen model从数据库生成模型
- gen provider生成依赖注入提供者 - gen provider生成依赖注入提供者
- gen route生成路由定义 - gen route生成路由定义
### 数据库命令 ## 数据库命令
- migrate执行数据库迁移 - migrate执行数据库迁移
- migrate up/down迁移或回滚 - migrate up/down迁移或回滚up 命令执行成功即表示数据库操作完成,无需其它确认操作。
- migrate status查看迁移状态 - migrate status查看迁移状态
- migrate create创建迁移文件迁移文件的命名需要使用动词名词的结合方式如 create_users_table, 创建完成后文件会存在于 `database/migrations` 目录下 - migrate create创建迁移文件迁移文件的命名需要使用动词名词的结合方式如 create_users_table, 创建完成后文件会存在于 `database/migrations` 目录下
### 最佳实践 ## 最佳实践
- migration 创建后需要执行 `atomctl migrate up` 执行数据库表迁移 - migration 创建后需要执行 `atomctl migrate up` 执行数据库表迁移
- 使用 gen model 前确保已migrate完成并配置好 database/transform.yaml - 使用 gen model 前确保已migrate完成并配置好 database/transform.yaml
- 对model中需要转换的数据结构声明在目录 `database/fields` 中文件名与model名一致 - 对model中需要转换的数据结构声明在目录 `database/fields` 中文件名与model名一致
- provider 生成时使用适当的注解标记 - provider 生成时使用适当的注解标记
- 遵循目录结构约定 - 遵循目录结构约定
## 项目结构 # 项目结构
## 标准目录
### 标准目录
- main.go主程序入口 - main.go主程序入口
- providers/:依赖注入提供者, 通过 atomctl gen provider 生成, 但是你不可以对其中的内容进行修改 - providers/:依赖注入提供者, 通过 atomctl gen provider 生成, 但是你不可以对其中的内容进行修改
- database/fields数据库模型字段定义 - database/fields数据库模型字段定义
- database/schemas数据库自动生成的模型文件 - database/schemas数据库自动生成的模型文件,不可以进行任何修改!!
- database/migrations: 数据库迁移文件,通过 atomctl migrate create 创建,你不可以手工创建,只可以使用脚手架工具进行创建 - database/migrations: 数据库迁移文件,通过 atomctl migrate create 创建,你不可以手工创建,只可以使用脚手架工具进行创建
- configs.toml配置文件 - configs.toml配置文件
- proto/ gRPC proto 定义 - proto/ gRPC proto 定义
@@ -102,10 +108,12 @@
- app/grpc: gRPC 服务 - app/grpc: gRPC 服务
- app/jobs: 后台任务定义 - app/jobs: 后台任务定义
- app/middlewares: HTTP 中间件 - app/middlewares: HTTP 中间件
- app/services: 服务启动逻辑,不可以进行任何修改
## 开发示例 # 开发示例
## migration 定义
### migration 定义
migration 文件示例. migration 文件示例.
``` ```
-- +goose Up -- +goose Up
@@ -115,10 +123,8 @@ migration 文件示例.
-- +goose StatementEnd -- +goose StatementEnd
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
-- +goose Down -- +goose Down
-- +goose StatementBegin -- +goose StatementBegin
@@ -127,20 +133,23 @@ migration 文件示例.
-- +goose StatementEnd -- +goose StatementEnd
``` ```
### migration sql 编写原则 ## migration sql 编写原则
1. 数据库表需要按需要添加 `created_at` `updated_at` `deleted_at` 字段 1. 数据库表需要按需要添加 `created_at` `updated_at` `deleted_at` 字段
2. 这三个时间字段(`created_at` `updated_at` `deleted_at`)需要直接位于 id 字段后面, 避免后期数据库表字段变更造成字段混乱。 2. 这三个时间字段(`created_at` `updated_at` `deleted_at`)需要直接位于 id 字段后面, 避免后期数据库表字段变更造成字段混乱。
3. 所有表不使用 `FOREIGN KEY` 约束,而是在业务中使用代码逻辑进行约束。 3. 所有表不使用 `FOREIGN KEY` 约束,而是在业务中使用代码逻辑进行约束。
4. 所有字段需要添加中文注释 4. 所有字段需要添加中文注释
### http module ## http module
1. 创建一个新的 http module `atomctl new module [users]` 1. 创建一个新的 http module `atomctl new module [users]`
2. 在 `app/http` 目录下创建相关的处理程序。 2. 在 `app/http` 目录下创建相关的处理程序。
3. 定义用户相关的路由。 3. 定义用户相关的路由。
4. 实现相关逻辑操作 4. 实现相关逻辑操作
5. module 名称需要使用复数形式,支持多层级目录,如 `atomctl new module [users.orders]` 5. module 名称需要使用复数形式,支持多层级目录,如 `atomctl new module [users.orders]`
### controller ## controller
- controller 的定义 - controller 的定义
```go ```go
// @provider // @provider
@@ -195,7 +204,8 @@ func (c *OrderController) List(ctx fiber.Ctx, claim *jwt.Claims,channel string,
- @Bind 参数会有几个位置 path/query/body/header/cookie/local/file 会分别从 url/get query/post body/header/cookie/fiber.Local/file/中取出所需要的数据绑定到方法的请求参数中去。 - @Bind 参数会有几个位置 path/query/body/header/cookie/local/file 会分别从 url/get query/post body/header/cookie/fiber.Local/file/中取出所需要的数据绑定到方法的请求参数中去。
- controller 只负责数据的接收返回及相关数据装饰具体的复杂逻辑实现需要在service文件中定义。 - controller 只负责数据的接收返回及相关数据装饰具体的复杂逻辑实现需要在service文件中定义。
### service ## service
- service 的定义 - service 的定义
```go ```go
// @provider // @provider
@@ -228,7 +238,7 @@ func (svc *Service) GetUserOrderByOrderID(ctx context.Context, orderID string, u
var order model.Orders var order model.Orders
if err := stmt.QueryContext(ctx, svc.db, &order) ; err != nil { if err := stmt.QueryContext(ctx, svc.db, &order) ; err != nil {
span.RecordError(err) span.RecordError(err)
return nil, err return nil, err
} }
return &order, nil return &order, nil
@@ -268,7 +278,7 @@ func (svc *Service) UpdateStage(ctx context.Context, tenantID, userID, postID in
) )
span.SetAttributes(semconv.DBStatementKey.String(stmt.DebugSql())) span.SetAttributes(semconv.DBStatementKey.String(stmt.DebugSql()))
if _, err := stmt.ExecContext(ctx, svc.db); err != nil { if _, err := stmt.ExecContext(ctx, svc.db) ; err != nil {
span.RecordError(err) span.RecordError(err)
return err return err
} }
@@ -318,7 +328,8 @@ func (s *ServiceTestSuite) Test_Service() {
} }
``` ```
### grpc ## grpc
- 一个 handler 的示例 - 一个 handler 的示例
``` ```
import ( import (
@@ -346,9 +357,13 @@ func (u *Users) GetUser(ctx context.Context, in *userv1.GetUserRequest) (*userv1
``` ```
# 本项目说明
## 本项目说明 - 设计一个支持多租户的用户系统,一个用户可以同时属于多个租户
1. 设计一个支持多租户的用户系统,一个用户可以同时属于多个租户 - 每一个租户有一个租户管理员角色,这个角色可以在后台由系统管理员指定,或者用户在申请创建租户申请时自动指定。
2. 每一个租户有一个租户管理员角色,这个角色可以在后台由系统管理员指定,或者用户在申请创建租户申请时自动指定 - 除系统管理员外,一个普通用户只可以是一个租户管理员,不能同时管理多个租户
3. 除系统管理员外,一个普通用户只可以是一个租户的管理员,不能同时管理多个租户。
4. 严格按照 <migration sql 编写原则> 的要求进行sql 生成 **重要提示:**
- 严格按照 《migration sql 编写原则》 的要求进行sql 生成
- `database/schemas` 目录下所有为件为 `atomctl gen model` 自动生成,不能进行任何修改!
- SQL 中不要使用 `FOREIGN KEY` 约束,而是在业务中使用代码逻辑进行约束。