按类型分组 const 声明,按逻辑和/或类型分组 var

  1. // BAD
  2. const (
  3. foo = 1
  4. bar = 2
  5. message = "warn message"
  6. )
  7. // MOSTLY BAD
  8. const foo = 1
  9. const bar = 2
  10. const message = "warn message"
  11. // GOOD
  12. const (
  13. foo = 1
  14. bar = 2
  15. )
  16. const message = "warn message"

这个模式也适用于 var

  1. defer func() {
  2. err := ocp.Close()
  3. if err != nil {
  4. rerr = err
  5. }
  6. }()
  • 不要在 checkErr 函数中使用 panic()os.Exit()
  • 仅仅在很特殊情况下才使用 panic, 你必须要去处理 error
  • 不要给枚举使用别名,因为这打破了类型安全
  1. package main
  2. type Status = int
  3. type Format = int // remove `=` to have type safety
  4. const A Status = 1
  5. const B Format = 1
  6. func main() {
  7. println(A == B)
  8. }
  • 如果你想省略返回参数,你最好表示出来

    • _ = f()f() 更好
  • 我们用 a := []T{} 来简单初始化 slice

  • 用 range 循环来进行数组或 slice 的迭代
    • for _, c := range a[3:7] {...}for i := 3; i < 7; i++ {...} 更好
  • 多行字符串用反引号(`)
  • _ 来跳过不用的参数
  1. func f(a int, _ string) {}
  • 如果你要比较时间戳,请使用 time.Beforetime.After ,不要使用 time.Sub 来获得 duration (持续时间),然后检查它的值。
  • 带有上下文的函数第一个参数名为 ctx,形如:func foo(ctx Context, ...)
  • 几个相同类型的参数定义可以用简短的方式来进行
  1. func f(a int, b int, s string, p string)
  1. func f(a, b int, s, p string)
  1. var a []string
  2. b := []string{}
  3. fmt.Println(reflect.DeepEqual(a, []string{}))
  4. fmt.Println(reflect.DeepEqual(b, []string{}))
  5. // Output:
  6. // false
  7. // true
  • 不要将枚举类型与 <, >, <=>= 进行比较
    • 使用确定的值,不要像下面这样做:
  1. value := reflect.ValueOf(object)
  2. kind := value.Kind()
  3. if kind >= reflect.Chan && kind <= reflect.Slice {
  4. // ...
  5. }
  1. func f1() {
  2. var a, b struct{}
  3. print(&a, "\n", &b, "\n") // Prints same address
  4. fmt.Println(&a == &b) // Comparison returns false
  5. }
  6. func f2() {
  7. var a, b struct{}
  8. fmt.Printf("%p\n%p\n", &a, &b) // Again, same address
  9. fmt.Println(&a == &b) // ...but the comparison returns true
  10. }
  • 包装错误: http://github.com/pkg/errors

    • 例如: errors.Wrap(err, "additional message to a given error")
  • 在 Go 里面要小心使用 range:

  • 从 map 读取一个不存在的 key 将不会 panic

    • value := map["no_key"] 将得到一个 0 值
    • value, ok := map["no_key"] 更好
  • 不要使用原始参数进行文件操作

    • 而不是一个八进制参数 os.MkdirAll(root, 0700)
    • 使用此类型的预定义常量 os.FileMode
  • 不要忘记为 iota 指定一种类型

  1. const (
  2. _ = iota
  3. testvar // testvar 将是 int 类型
  4. )

vs

  1. type myType int
  2. const (
  3. _ myType = iota
  4. testvar // testvar 将是 myType 类型
  5. )