衡量代码质量的唯一标准是阅读该代码时说脏话的次数
一个优秀的团队应当保持一致的代码风格,我们在实践中发现,如果一个项目的代码风格不一致,会导致项目杂乱、不利于跨模块开发、影响开发效率、想骂人等弊端,
在定义我们的编码风格之前,先推荐一本非常好的书籍《clean code》,有时间的可以去看看,磨刀不误砍柴工。
buf
而不是bufio
少用调用者去起别名,除非名字太烂
样例:
Bad:
configs
third_party
thirdParty
...
(1)如果程序包名称与导入路径的最后一个元素不匹配,则必须使用导入别名
import (
client "example.com/client-go"
trace "example.com/trace/v2"
)
建议路径最后一个元素是版本号的都使用别名,避免歧义。
(2)在所有其他情况下,除非导入之间有直接冲突,否则应避免导入别名
import (
"net/http/pprof"
gpprof "github.com/google/pprof"
)
(3)如有重名,请保留标准包命名,别名自定义或者第三方包
(4)禁止使用相对路径导入,所有导入路径必须符合 go get 标准
样例:
Bad:
configs.yaml
cloudServer.go
cloud-server.go
样例:
Bad:
container.createContainer(in)
Good:
container.create(in)
Get
,设置器名字以 Set
开头note : 若你有个名为 owner (小写,未导出)的字段,其获取器应当名为 Owner(大写,可导出)而非 GetOwner。
样例:
Good:
func Owner() string {
...
}
func SetOwner(ower string) string {
...
}
Bad:
func GetOwner() string {
...
}
样例:
Bad:
func (u *userRepo) syncDepartmentFormDatabase() {
...
}
From而非Form。
type Reader interface {
Read(p []byte) (n int, err error)
}
type ContainerRepo interface {
Create() error
Delete() error
...
}
样例:
Good:
type Container struct {}
type ContainerInfo struct {}
Bad:
type ContainerDelete struct {}
type Containers struct {}
type Containerinfo struct {}
type Scheme string
const (
Http Scheme = "http"
Https Scheme = "https"
)
type Symbol string
const (
SymbolAdd Symbol = "+"
SymbolSub Symbol = "-"
)
// configPath is the absolute path of config file from the command line.
var configPath string
user 可以简写为 u
userId 可以简写 uid
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool
Error
类型的命名以Error
结尾type CodeError struct {
message string
}
Error
类型的变量,以Err
开头var ErrTokenExpired = errors.New("token expired")
Error
的变量缩写采用err
func test() {
res, err := container.create(in)
...
}
样例:
Good:
func (c *container)Update(ctx context.Context,name string) error {
res, listErr := c.list()
if listErr!=nil {
return listErr
}
updateErr := c.update(name)
if updateErr!=nil {
return updateErr
}
...
}
Bad:
func (c *container)Update(ctx context.Context,name string) error {
res, err := c.list()
if err!=nil {
return err
}
_, err = c.update(name)
if err!=nil {
return err
}
...
}
/
表明层级关系-
来提高长路径中名称的可读性,不得在 URL 中使用下划线_
/
Bad:
/GetUserInfo
/photos_path
/My-Folder/my-doc/
/user/user-list
Good:
/user/list
/user/operator-logs
message CreateSecurityGroupRequest {}
message CreateSecurityResponse {}
// 除了request和response外,其他的命名风格需保持名词形式
message SecurityGroupInfo{}
enum Policy{}
举个例子:标准包http
包提供的 HTTP 服务名为 http.Server
,而非 HTTPServer
。用户代码通过 http.Server
引用该类型,因此没有歧义。
package http
type Server struct {}
举个例子:标准库中含有多个名为 Reader 的类型,包括 jpeg.Reader
、 bufio.Reader
和 csv.Reader
。每个包名搭配 Reader 都是个不错的类型名。
package jpeg
type Reader struct {}
package bufio
type Reader struct {}
我们没有太多可选的余地,因为 Go 已经规范好了,在 Go 世界没有此类战争。
id
这个字段,为了简明易懂无歧义,我们规定,在一个结构体中,凡是涉及到id
字段的,都必须要加上前缀,用以区分type SecurityGroup struct {
SgID string `json:"sg_id"`
Rule Rule `json:"rule"`
...
}
type Rule struct {
RuleID string `json:"rule_id"`
...
}
样例:
Good:
func Create() error {
if err:=container.create();err!=nil {
return err
}
if err:=store.update();err!=nil {
return err
}
...
}
func check() error {
isExist, err := contaier.check()
if err!=nil {
return err
}
if isExist {
...
}
if err:=store.update();err!=nil {
return err
}
...
}
样例:
Bad:
func test() error {
if err:=container.create();err!=nil {
return err
}
...
}
func test() error {
fmt.Println("test")
return nil
}
import (
"flag"
"os"
"github.com/go-kratos/kratos/v2"
"github.com/go-kratos/kratos/v2/config"
"github.com/go-kratos/kratos/v2/config/file"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/middleware/tracing"
"github.com/go-kratos/kratos/v2/transport/grpc"
"github.com/go-kratos/kratos/v2/transport/http"
"backend/internal/conf"
"backend/internal/data"
)