一. Gofmt
- 必须使用Gofmt做代码格式化和自动优化
- 如果使用Goland IDE开发可以选择goimports, goimports包含了Gofmt的功能同时还支持自动添加和删除package导入功能
Goland -> Preferences -> File Watchers -> 添加goimports
二. Comment Sentences
- 每个Go文件头部都应该有注释, 注释内容包括文件创建者、时间和功能描述。按下面的格式进行注释
// Package test
// Created by chenguolin 2018-05-02
// ......
package test
struct、interface、function注释应该使用"//“开头以”."结束, 并且保证注释句子完整如果是英文注释首字母还必须是大写
例如**// Request represents a request to run a command.**常量、变量等定义注释应该使用"//“开头以”."结束, 并且保证注释句子完整如果是英文注释首字母还必须是大写
例如**// Username variable define.**通过注释写的TODO需要保证开发者能够明白还有什么事项是TODO的
例如**// TODO: 串行处理可以改成Goroutine并发处理**
三. Contexts
- context.Context可以用来传递上下文相关的信息,Go语言RPC和HTTP请求通过显式把Context传递到整个函数调用链来传递上下文信息
- 很多函数使用Context做为它的第一个参数
func F(ctx context.Context, /* other arguments */) {} - Context只用于传递上下文相关的信息,并且Context是不可改变的
四. Imports
- 如果你的包引入了三种类型的包,标准库包,程序内部包,第三方包,建议采用如下方式进行组织你的包
package main
import (
"encoding/json"
"strings"
"myproject/models"
"myproject/controller"
"myproject/utils"
"github.com/astaxie/beego"
"github.com/go-sql-driver/mysql"
)
- 在项目中不要使用相对路径引入包,使用绝对路径引入包
package main
import "../net" (这是不好的导入)
import "github.com/repo/proj/src/net" (这是正确的做法)
- 不要使用**.**来省略包名引用
package main
import (
"bar/testutil"
. "foo" (不要这样使用)
)
五. Declaring
- package命名要求和目录名保持一致,尽量采取有意义的包名,简短,有意义,尽量和标准库不要冲突
- struct命名采用"驼峰法",并且通过首字母大小写来控制是否包外可见
- interface命名: 采用"驼峰法",并且通过首字母大小写来控制是否包外可见
- 单个函数的接口名以"er"作为后缀,例如type Reader interface {…}
- 两个函数的接口名综合两个函数名,例如type WriteFlusher interface {…}
- 三个以上函数的接口名,类似于结构体名,例如type Car interface {…}
- const命名每个字母都是大写,并且采用"下划线"分割
例如const REDIS_LOGIN_KEY = "redis_login_key" - 变量命名采用"驼峰法",例如var userName string。
- 函数命名采用"驼峰法",并且通过首字母大小写来控制是否包外可见
例如func userLogin() error {}
六. Indent
为了保证最小的代码缩进和代码可读性,有一些缩进的规范,如下所示
不好的写法
if err != nil {
error handling
} else {
normal code
}
正确的写法
if err != nil {
error handling
return
}
normal code
不好的写法
if x, err := f(); err != nil {
error handling
return
} else {
use x
}
正确的写法
x, err := f()
if err != nil {
error handling
return
}
use x
七. Initialisms
- 特殊名词的首字母缩写需要按照规范来,例如URLProxy或者urlProxy不要命名为UrlProxy
- ID表示"Identity Document",不能缩写为Id,例如正确命名是appID而不是appId
八. General
- package命名应该尽可能的简短并且所有字母都应该是小写,例如
package chubby - receiver命名最多2个字母,不能使用me或者self或者this,例如
func (c *Client) GetUserName() string - 每行代码长度最好不超过80个字符,如果超过建议换行
- 函数参数定义
- 参数类型不是map,slice或者chan需要采用传"指针"类型而不是传"值"类型,例如
func (s *Service) Login(args *loginArgs) error {} - 参数类型是map,slice或者chan,不要用指针传递
- 参数类型不是map,slice或者chan需要采用传"指针"类型而不是传"值"类型,例如
- 函数返回值采用返回"指针"类型而不是返回"值"类型
- 错误处理的原则是不能忽略任何error,不要使用"_"丢弃,必须全部处理
接收到错误,要么返回error给上层调用,要么使用log打印对应的error和warn信息 - log信息应该输出"[fileName - function]"前缀,在排查问题的时候能够快速定位到出问题的代码
- 强烈建议不要乱抛panic,因为panic会导致进程crash
- 任何一个goroutine都应该有recover来保护程序不会因为panic而crash,因为任何一个goroutine如果抛panic但没有recover整个程序会crash
- 业务逻辑函数需要把每个步骤耗时打印出来,有助于分析排查问题
版权声明:本文为cgl1079743846原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。