# Go通用Web项目编码风格/规范 ## 使用的包 * HTTP使用gin框架 * ORM使用GORM框架 * Postgre的驱动使用`gorm.io/driver/postgres` * Mysql驱动使用`gorm.io/driver/mysql` ## 代码目录结构 ```txt magi-forge/ ├── web/ # 前端项目 ├── app/ # 应用层 │ └── model/ # 数据模型 │ └── service/ # 业务逻辑层 │ └── api/ # API 层 (Controller层) │ └── common/ # 通用代码, 包括错误定义, 响应格式等 ├── cmd/ # 命令行入口 │ └── apiserver/ # API 服务器 │ └── xxxx/ # 其他CLI或服务 └── pkg/ # 可复用包 ├── autoload/ # 自动加载器, 用于统一按照执行顺序加载所有全局单例 ├── config/ # 配置管理, 用于管理所有配置项 ├── dao/ # 数据访问层, 用于访问外部服务, 包括数据库, Redis, 外部HTTP Client等 └── logger/ # 用于统一日志输出 ``` ## 全局单例说明 默认需要全局单例的包有: - config - dao * 全局单例包必须实现Get()方法, 用于获取单例实例 * 全局单例包必须实现Autoload()方法, 用于给autoload包调用, 用于创建全局单例实例 * 如果用户指定了其他全局单例, 则需要参照以上说明实现 ## autoload包说明 autoload包必须实现autoload.go文件的Autoload()方法,且不传递和返回任何参数, 出错就直接panic Autoload方法有执行顺序, 其中config包必须第一个调用, 其他全局单例包的Autoload方法根据实际情况调用 ## model层(GORM模型声明规范) **需要时必须显示声明的注解包括** * column * primaryKey * autoIncrement * type * json * 指针类型需要定义json omitempty标签, 避免在json序列化时出现空值 **必须实现的方法包括** * TableName() string **关联模型要求** * 关联的对象均使用指针, 避免没有Preload时关联对象是默认值对象 * Migrate时不允许创建实际的外键, 也就是Dao需要配置`DisableForeignKeyConstraintWhenMigrating: true,` ### PostgreSQL 模型声明规范 * 数组采用github.com/lib/pq中的各种Array类型 * jsonb采用datatypes.JSONType[Go Struct] ## API(Controller)层编码规范 * 每一组业务的Controller都用一个struct承载, 但是struct里不要放入注入任何对象 * 业务需要的Service在每次实际调用时直接NewService * Controller不要编写复杂业务逻辑, 而是组合1个或多个Service * 路由定义在`app/api/routes_define.go`文件的`RegisterRoutes`方法中 * API不需要版本前缀 * 路由必须有/api前缀 ### 标准API响应 * 无特殊要求时所有API都返回JSON格式, 包含code, message, data三个字段 * code为int类型, 0表示成功, 其他值表示失败 * message为string类型, 用于描述失败原因 * data为任意类型, 用于返回业务数据 * Code需要在common包中的`code.go`中定义 **示例** ```json { "code": 0, "message": "ok", "data": {} } ``` 可以直接使用common包中的`response.go`定义的方法 ## Service层编码规范 * 每一组业务的Service都用一个struct承载, 但是struct里不要放入注入任何对象 * Service每个需要数据库操作的方法, 第一个参数都需要传递一个tx *gorm.DB, 用于数据库事务 * 每个Service需要实现一个NewService方法, 但是没有要求时不需要传递任何函数, 直接返回Service{}即可 ## 前端规范 * 后端暴露/ui/*路径, 用于前端访问 * 后端的/直接跳转/ui/路径 * 使用Next.js + Ant Design6作为后台框架 * 后台如果有代码编写组件使用Monaco Editor * 默认不需要开发任何认证、鉴权部分 * 后台管理使用左右栏布局, 左侧为菜单, 右侧为内容区域 * API定义读取后端代码 * 尽量借鉴后端model的注释来理解需求 * 访问后端接口使用相对路由 ## 其他编码规范 * 默认代码只分api -> service -> model三层, 没有特殊要求不要引入repo层等 * 没有额外要求时不编写单元测试 * 不要过度设计, 不复杂的代码不要刻意拆分额外的函数 * 项目的业务代码主要使用全局单例 * 使用`any`而不是`interface{}`