编码规范

此开源图书由ithaiqarrow-up-right原创,创作不易转载请注明出处

代码格式化

注意:代码都必须用 gofmt 进行格式化,文件长度800行,函数长度80行

包引用

// bad
"github.com/dgrijalva/jwt-go/v4"
//good
jwt "github.com/dgrijalva/jwt-go/v4"
//注意顺序
import (
	// go 标准包
	"fmt"
	
	// 第三方包
	"github.com/jinzhu/gorm"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	
	// 匿名包单独分组,并对匿名包引用进行说明
	// import mysql driver
	_ "github.com/jinzhu/gorm/dialects/mysql"
	
	// 内部包
	v1 "github.com/marmotedu/api/apiserver/v1"
	metav1 "github.com/marmotedu/apimachinery/pkg/meta/v1"
	"github.com/marmotedu/iam/pkg/cli/genericclioptions"
)

声明、初始化和定义

错误处理

panic使用:业务逻辑处理中禁止使用panic; 在main包中使用 log.Fatal 来记录错误。

命名规范

  • 包名

    • 包名必须和目录名一致

    • 包名全部小写,没有大写或下划线,使用多级目录来划分层级

    • 项目名可以通过中划线来连接多个单词。

    • 包名以及包所在的目录名,不要使用复数。

    • 不要用 common、util、shared 或者 lib 这类宽泛的、无意义的包名

    • 包名要简单明了,例如 net、time、log

  • 函数命名

    • MixedCaps或者mixedCaps 控制权限

  • 文件名

    • 文件名要简短有意义、文件名应小写,并使用下划线分割单词

  • 接口命名

    • 单个函数的接口名以 “er"”作为后缀

  • 变量命名

    • 特有名词(全大写)

    • 若变量类型为bool类型,则名称应以Has,Is,Can或Allow开头

    • 局部变量应当尽可能短小 buf⇒buffer

  • 常量命名

  • error命名

基础类型

  • 字符串

  • []byte和string比较

  • 空slice map、channel 判断

  • slice

流程控制

  • 不要在 for 循环里面使用 defer,defer只有在函数退出时才会执行

  • range

  • goto不要用

函数

  • 尽量采用值传递,而非指针传递

  • 传入参数是 map、slice、chan、interface ,不要传递指针

  • 如果函数返回相同类型的两个或三个参数,或者如果从上下文中不清楚结果的含义,使用命名返回,其他情况不建议使用命名返回

  • 先判断是否错误,再defer释放资源

依赖管理

  • Go 1.11 以上必须使用 Go Modules。

  • 使用Go Modules作为依赖管理的项目时,不建议提交vendor目录。

  • 使用Go Modules作为依赖管理的项目时,必须提交go.sum文件

最佳实践

  • 尽量少用全局变量,而是通过参数传递

  • 编译验证接口

  • 性能

    • string 表示的是不可变的字符串变量,对 string 的修改是比较重的操作,基本上都需要重新申请内存。所以,如果没有特殊需要,需要修改时多使用 []byte。

    • 优先使用 strconv 而不是 fmt

  • 注意事项

    • append 要小心自动分配内存,append 返回的可能是新分配的地址。

    • 如果要直接修改 map 的 value 值,则 value 只能是指针,否则要覆盖原来的值。

    • map 在并发中需要加锁。

    • 编译过程无法检查 interface{} 的转换,只能在运行时检查,小心引起 panic。

最后更新于