golang 代码规范

  • 变量
    • 变量越重要,生存周期越长,变量名越长
    • 变量名不应该包含类型信息
    • 变量名应该和默认值相符合
      • 例如isCacheDsiabled要比isCacheEnabled 好,因为默认值是false
    • 首字母应该默认小写,尽量减少作用域
    • 变量的分组声明也可以用在函数内部
    • 非导出的全局变量应该以下划线开头
      • 避免与函数内部变量重名导致不可预料的bug
    • 结构体的嵌入类型(例如mutex)应该放在开头,且和常规字段分开
    • 用于格式化的字符串应该放在printf外面,并用const修饰
    • 尽量利用type 创建新的具体的类型代替宽泛的[]int等基本类型
      • 好处是可以自定义新方法
  • 函数
    • 函数不应该超过50行
    • 一个函数应该只做一件事
    • 使用接口参数让函数自己定义它所需要的行为
    • 如果你的函数开启了一个协程,应该返回个调用者一个关闭协程的函数
    • 尽量不使用命名返回值
    • 如果要忽略返回值,应该使用 _ = f() 显示指出
    • for-select 语句换成一个函数
  • 方法
    • 如果不清楚使用值接受者还是指针接受者,使用指针接受者
  • 并发
    • 以线程安全的方式创建一些东西的最好选择是 sync.Once
      • 例如配置的初始化
  • 网络
    • 总是关闭http的body: defer r.Body.Close()
      • 应该先检查 HTTP 响应错误为 nil,再调用 resp.Body.Close() 来关闭响应体
  • init函数
    • 不要在init函数中执行初始化等操作
      • 如果另一个 package 依赖了当前的包,那么引入这个依赖的工程师可能会在遇到错误时非常困惑
    • 们不应该在 init 中做过重的初始化逻辑,而是做一些简单的前置条件判断
  • 错误处理
    • 向上抛出错误时可以通过 errors.Wrap 携带一些额外的信息方便上层进行判断
  • 其他
    • 多个if语句考虑用switch代替
    • 用 chan struct{} 来传递信号, chan bool 表达的不够清楚
    • 每个阻塞或者 IO 函数操作应该是可取消的或者至少是可超时的
    • 如果你要比较时间戳,请使用 time.Beforetime.After ,不要使用 time.Sub来获得 duration ,然后检查它的值
    • 不要忘记停止 ticker
      • ticker := time.NewTicker(1 * time.Second); defer ticker.Stop()
    • 判断slice为空时,判断长度而不是nil
    • 从slice中切出新slice时,重新声明新slice并拷贝旧slicecopy(new, old)
      • 否则旧底层大数组不会释放,造成内存超标

参考

Go 语言实践:编写可维护的程序的建议

Go code review comments

Uber Go 风格指南

Effective go

go-advice

如何写出优雅的 Golang 代码

Golang 新手可能会踩的 50 个坑

发布了161 篇原创文章 · 获赞 19 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/winter_wu_1998/article/details/102926479