Golang项目规范
...大约 7 分钟
一 说明
1.1 编程规范统一,可避免陷于语言陷阱,有利于团队协作
1.2 统一目录组织结构,避免目录及文件名随意
1.3 ide配置保存代码自动gofmt,goimports
1.4 使用go mod管理第三包
1.5 tag键设置为4个字符
二 项目源码组织结构
项目源码组织结构参考以下,建议都按以下结构开新项目
.
├── README.md
├── cmd # 定义启动命令
│ ├── admin #运营后台接口
│ │ └── admin.go
│ ├── api #app/h5接口
│ │ └── api.go
│ └── cmd.go
├── conf #配置文件存放目录
│ ├── in-dev.yaml #开发环境配置
│ └── in-prod.yaml #生产环境配置
├── data #临时文件存放目录
│ └── logs #日志文件存放目录
├── docs #接口文档存放目录
│ ├── admin #运营后台接口文档
│ │ ├── docs.go
│ │ ├── swagger.json
│ │ └── swagger.yaml
│ └── api #app/h5接口文档
│ ├── docs.go
│ ├── swagger.json
│ └── swagger.yaml
├── internal #内部包
│ ├── admin #运营后台接口
│ │ ├── controller #控制器存放目录
│ │ │ └── base.go
│ │ └── router #路由
│ │ └── router.go
│ ├── api #app/h5接口
│ │ ├── controller #控制器存放目录
│ │ │ └── base.go
│ │ └── router #路由
│ │ └── router.go
│ └── common #公共目录
│ ├── dao #dao层,操作数据库
│ │ └── dao.go
│ ├── dto #dto层,定义传输对象,用于表单验证等
│ │ └── dto.go
│ ├── middleware #中间件
│ │ └── middleware.go
│ ├── model #model层,定义struct与数据库的映射关系
│ │ └── model.go
│ └── service #服务层,业务逻辑主要都写在这一层
│ └── service.go
├── main.go #入口文件
├── pkg #外部包,一些不依赖内部包(internal)的代码都存放在此
│ ├── cache #缓存包
│ │ └── cache.go
│ ├── logger #日志包
│ │ └── logger.go
│ └── utils #公共工具类函数包
│ ├── strings.go
│ └── utils.go
└── scripts #脚本存放目录
├── init.sh
└── init.sql
三 代码规范
3.1 包
- 全部使用小写,不用驼峰命名方式,不使用下划线、中划线,与外层目录名相同,尽量和标准库包名不要冲突
- 命名要有意义,一看包名就能知道这个包的用途
举例:
// 符合规范
package files
package logger
//不符合规范
package testAbc
package test_abc
package os // 与标准包冲突
- 一个目录只包含一个包,模块复杂拆分子模块/子目录
- 禁止相对路径导入包
举例:
// 不符合规范
import ./pkg/logger
- 建议goimports或者IDE管理import
3.2 文件
- 全部使用小写,不用驼峰命名方式,多个单词可以使用下划线'_',首尾不能使用下划线
- 命名要有意义,一看文件名就能知道这个文件的大概内容,不需要再出现包名。
- 统一使用单数形式
举例:
//符合规范:
user_info.go
user_email.go
client.go
server.go
//不符合规范
_abc.go
abc_.go
111.go
3.3 变量
- 全局变量,采用驼峰命名方式,当遇到特有名词(缩写或简称,如:DNS)的时候,特有名词根据是否私有全部大写或小写。
例子:apiClient、URLString
- 局部变量,采用小驼峰命名方式,声明局部变量尽量使用 :=
3.4 常量
- 同变量规则,力求语义表达完整清楚,不要嫌名字长。
- 如果模块复杂,为避免混淆,可按功能统一定义在package下的一个文件中。
- 不允许下划线,第三方包例外。
3.5 结构体
- 声明使用驼峰命名方式,禁止使用下划线命名
举例:
// 符合规范
type UserService struct
}
// 不符合规范
type User_Service struct {
}
type user_service struct {
}
- 结构体内字段使用驼峰式命名,禁止使用下划线命名,根据实际情况使用tag
例子:
type UserService struct{
// 符合规范
UserName string `json:"user_name"`
// 不符合规范
User_Name string `json:"user_name"`
}
- 结构体使用名词或者动名词
3.6 接口interface
- 命名使用驼峰式命名,首字母大写,禁止使用下划线
- 接口名以'er'为后缀,如:Reader,Writer
举例:
//符合规范
type Reader interface{
}
type Writer interface{
}
//不符合规范
type Read interface{
}
type Write interface{
}
type Test_interface interface{
}
3.7 函数
- 使用驼峰式命名,禁止使用下划线
- 建议动词或者动宾结构单词
- 参数使用驼峰式命名,首字母使用小写,禁止使用下划线
- 参数按紧密程度安排位置,同类型参数应该相邻
- 参数建议不大于5个
3.8 方法
- 与函数名规则一致
- 如果是结构体方法,那么 Receiver 的名称应该缩写,一般使用一个或者两个字符作为 Receiver 的名称。如果 Receiver 是指针, 那么统一使用p。 如
// 接收拷贝
func (f foo) method() {
...
}
// 接收指针
func (p *foo) method() {
...
}
- 对于Receiver命名应该统一, 要么都使用值, 要么都用指针。
3.9 错误处理
- 错误处理的原则就是不能丢弃任何有返回err的调用,不要使用 _ 丢弃,必须全部处理
- 接收到错误,要么返回err,或者使用log记录下来,尽早return:一旦有错误发生,马上返回
- 尽量不要使用panic,除非你知道你在做什么
举例:
// 错误写法
if err != nil {
} else {
}
// 正确写法
if err != nil {
return
}
3.10 注释规范
注释可以帮我们很好的完成文档的工作,写得好的注释可以方便我们以后的维护。和其他语言类似,go 语言也提供了 /**/ 的块注释和 // 的单行注释两种注释风格, 在我们的项目中为了风格的统一,全部使用单行注释。go 语言自带的 godoc 工具可以根据注释生成文档,生成可以自动生成对应的网站( golang.org 就是使用 godoc 工具直接生成的),注释的质量决定了生成的文档的质量。
四 Restful API路由设计标准
4.1 协议
api接口统一使用https协议
4.2 域名
使用独立的二级域名,不占用主域名
4.3 版本
在URL中放入版本号
4.4 路径
在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数。
举例来说,有一个API提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样。
4.5 HTTP动词
常用的HTTP动词有下面五个(括号里是对应的SQL命令)。
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
- DELETE(DELETE):从服务器删除资源
DEMO:
- GET /zoos:列出所有动物园
- POST /zoos:新建一个动物园
- GET /zoos/ID:获取某个指定动物园的信息
- PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
- PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
- DELETE /zoos/ID:删除某个动物园
- GET /zoos/ID/animals:列出某个指定动物园的所有动物
- DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
4.6 过滤信息
常见过滤参数
- ?limit=10:指定返回记录的数量
- ?offset=10:指定返回记录的开始位置。
- ?page=2&per_page=100:指定第几页,以及每页的记录数。
- ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
- ?animal_type_id=1:指定筛选条件
4.7 状态码
- 200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
- 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
- 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
- 204 NO CONTENT - [DELETE]:用户删除数据成功。
- 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
- 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
- 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
- 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
- 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
- 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
- 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
- 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
Powered by Waline v2.15.5