1 . 多个 if 语句可以折叠成 switch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| if foo() { } else if bar == baz { } else { }
switch { case foo(): case bar == baz: default: }
|
2 . 用 chan struct{} 来传递信号, chan bool 表达的不够清楚
当你在结构中看到 chan bool 的定义时,有时不容易理解如何使用该值,例如:
1 2 3
| type Service struct { deleteCh chan bool }
|
但是我们可以将其改为明确的 chan struct {} 来使其更清楚:我们不在乎值(它始终是 struct {}),我们关心可能发生的事件,例如:
1 2 3
| type Service struct { deleteCh chan struct{} }
|
3 . time.Second 比 time.Duration(30) * time.Second 更好
你不需要将无类型的常量包装成类型,编译器会找出来。
另外最好将常量移到第一位:
1 2 3 4 5
| delay := time.Second * 60 * 24 * 60
delay := 24 * 60 * 60 * time.Second
|
4 . 用 time.Duration 代替 int64 + 变量名
1 2 3 4 5
| var delayMillis int64 = 15000
var delay time.Duration = 15 * time.Second
|
5. 按类型分组 const 声明,按逻辑和/或类型分组 var
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const ( foo = 1 bar = 2 message = "warn message" )
const foo = 1 const bar = 2 const message = "warn message"
const ( foo = 1 bar = 2 )
const message = "warn message"
|
6 要比较时间戳,请使用 time.Before 或 time.After ,不要使用 time.Sub 来获得 duration (持续时间),然后检查它的值。
7. 用 %+v 来打印数据的比较全的信息
8. 在 Go 里面要小心使用 range
1 2
| for i := range a and for i, v := range &a ,都不是 a 的副本 但是 for i, v := range a 里面的就是 a 的副本
|
9. 不要忘记停止 ticker
1 2
| ticker := time.NewTicker(1 * time.Second) defer ticker.Stop()
|
10.所有代码都应该通过golint和go vet的检查并无错误。
11. 零值 sync.Mutex
和 sync.RWMutex
是有效的。所以指向 mutex 的指针基本是不必要的。
1 2
| var mu sync.Mutex mu.Lock()
|
12. Channel 的 size 要么是 1,要么是无缓冲的
1 2
| c := make(chan int, 1) c := make(chan int)
|
13. 枚举从 1 开始
1 2 3 4 5 6 7
| type Operation int
const ( Add Operation = iota + 1 Subtract Multiply )
|
14. 使用 time.Time
表达瞬时时间
在处理时间的瞬间时使用 [time.Time](https://golang.org/pkg/time/#Time)
,在比较、添加或减去时间时使用 time.Time
中的方法。
1 2 3
| func isActive(now, start, stop time.Time) bool { return (start.Before(now) || start.Equal(now)) && now.Before(stop) }
|
15. 在尽可能的情况下,在初始化要追加的切片时为make()
提供一个容量值。
16. 优先使用 strconv 而不是 fmt
17. 包命名
- 全部小写。没有大写或下划线。
- 大多数使用命名导入的情况下,不需要重命名。
- 简短而简洁。请记住,在每个使用的地方都完整标识了该名称。
- 不用复数。例如
net/url
,而不是net/urls
。
- 不要用“common”,“util”,“shared”或“lib”。这些是不好的,信息量不足的名称。
18. 嵌入式类型(例如 mutex)应位于结构体内的字段列表的顶部,并且必须有一个空行将嵌入式字段与常规字段分隔开。
19. 不应明确返回长度为零的切片。应该返回nil
来代替。
20. 要检查切片是否为空,请始终使用len(s) == 0
。而非 nil
。
21. time.After() 在某些情况下会发生泄露,替换为使用 Timer。
22. 读写磁盘时,使用读写 buffer。
23. 内存分配复用内存可以使用 sync.Pool
24. 频繁的字符串拼接操作(+=),替换为 StringBuffer 或 StringBuilder
25. 并发检测 race