GO编程:小技巧

Go 箴言

  • 不要通过共享内存进行通信,通过通信共享内存
  • 并发不是并行
  • 管道用于协调;互斥量(锁)用于同步
  • 接口越大,抽象就越弱
  • 利用好零值
  • 空接口 interface{} 没有任何类型约束
  • Gofmt 的风格不是人们最喜欢的,但 gofmt 是每个人的最爱
  • 允许一点点重复比引入一点点依赖更好
  • 系统调用必须始终使用构建标记进行保护
  • 必须始终使用构建标记保护 Cgo
  • Cgo 不是 Go
  • 使用标准库的 unsafe 包,不能保证能如期运行
  • 清晰比聪明更好
  • 反射永远不清晰
  • 错误是值
  • 不要只检查错误,还要优雅地处理它们
  • 设计架构,命名组件,(文档)记录细节
  • 文档是供用户使用的
  • 不要(在生产环境)使用 panic()
Go 之禅
  • 每个 package 实现单一的目的
  • 显式处理错误
  • 尽早返回,而不是使用深嵌套
  • 让调用者处理并发(带来的问题)
  • 在启动一个 goroutine 时,需要知道何时它会停止
  • 避免 package 级别的状态
  • 简单很重要
  • 编写测试以锁定 package API 的行为
  • 如果你觉得慢,先编写 benchmark 来证明
  • 适度是一种美德
  • 可维护性
代码使用go fmt格式化让团队一起使用官方的 Go 格式工具,不要重新发明轮子 。
尝试减少代码复杂度 。这将帮助所有人使代码易于阅读 。
多个 if 语句可以折叠成 switch// NOT BADif foo() {// ...} else if bar == baz {// ...} else {// ...}// BETTERswitch {case foo():// ...case bar == baz:// ...default:// ...}用chan struct{}来传递信号,chan bool表达的不够清楚当你在结构中看到 chan bool 的定义时,有时不容易理解如何使用该值,例如:
type Service struct {deleteCh chan bool // what does this bool mean? }但是我们可以将其改为明确的 chan struct {} 来使其更清楚:我们不在乎值(它始终是 struct {}),我们关心可能发生的事件,例如:
type Service struct {deleteCh chan struct{} // ok, if event than delete something.}30 * time.Second比time.Duration(30) * time.Second更好你不需要将无类型的常量包装成类型,编译器会找出来 。
另外最好将常量移到第一位:
// BADdelay := time.Second * 60 * 24 * 60// VERY BADdelay := 60 * time.Second * 60 * 24// GOODdelay := 24 * 60 * 60 * time.Second用time.Duration代替int64+ 变量名// BADvar delayMillis int64 = 15000// GOODvar delay time.Duration = 15 * time.Second按类型分组const声明,按逻辑和/或类型分组var// BADconst (foo = 1bar = 2message = "warn message")// MOSTLY BADconst foo = 1const bar = 2const message = "warn message"// GOODconst (foo = 1bar = 2)const message = "warn message"这个模式也适用于 var 。
  • 每个阻塞或者 IO 函数操作应该是可取消的或者至少是可超时的
  • 为整型常量值实现 Stringer 接口https://godoc.org/golang.org/x/tools/cmd/stringer
  • 检查 defer 中的错误
defer func() {err := ocp.Close()if err != nil {rerr = err}}()
  • 不要在 checkErr 函数中使用 panic() 或 os.Exit()
  • 仅仅在很特殊情况下才使用 panic, 你必须要去处理 error
  • 不要给枚举使用别名,因为这打破了类型安全https://play.golang.org/p/MGbeDwtXN3
package maintype Status = inttype Format = int // remove `=` to have type safetyconst A Status = 1const B Format = 1func main() {println(A == B)}