按类型分组 const
声明,按逻辑和/或类型分组 var
// BAD
const (
foo = 1
bar = 2
message = "warn message"
)
// MOSTLY BAD
const foo = 1
const bar = 2
const message = "warn message"
// GOOD
const (
foo = 1
bar = 2
)
const message = "warn message"
这个模式也适用于 var
。
- 每个阻塞或者 IO 函数操作应该是可取消的或者至少是可超时的
- 为整型常量值实现
Stringer
接口 - 检查
defer
中的错误
defer func() {
err := ocp.Close()
if err != nil {
rerr = err
}
}()
- 不要在
checkErr
函数中使用panic()
或os.Exit()
- 仅仅在很特殊情况下才使用 panic, 你必须要去处理 error
- 不要给枚举使用别名,因为这打破了类型安全
package main
type Status = int
type Format = int // remove `=` to have type safety
const A Status = 1
const B Format = 1
func main() {
println(A == B)
}
如果你想省略返回参数,你最好表示出来
_ = f()
比f()
更好
我们用
a := []T{}
来简单初始化 slice- 用 range 循环来进行数组或 slice 的迭代
for _, c := range a[3:7] {...}
比for i := 3; i < 7; i++ {...}
更好
- 多行字符串用反引号(`)
- 用
_
来跳过不用的参数
func f(a int, _ string) {}
- 如果你要比较时间戳,请使用
time.Before
或time.After
,不要使用time.Sub
来获得 duration (持续时间),然后检查它的值。 - 带有上下文的函数第一个参数名为
ctx
,形如:func foo(ctx Context, ...)
- 几个相同类型的参数定义可以用简短的方式来进行
func f(a int, b int, s string, p string)
func f(a, b int, s, p string)
- 一个 slice 的零值是 nil
- https://play.golang.org/p/pNT0d_Bunq
var s []int
fmt.Println(s, len(s), cap(s))
if s == nil {
fmt.Println("nil!")
}
// Output:
// [] 0 0
// nil!
- https://play.golang.org/p/pNT0d_Bunq
var a []string
b := []string{}
fmt.Println(reflect.DeepEqual(a, []string{}))
fmt.Println(reflect.DeepEqual(b, []string{}))
// Output:
// false
// true
- 不要将枚举类型与
<
,>
,<=
和>=
进行比较- 使用确定的值,不要像下面这样做:
value := reflect.ValueOf(object)
kind := value.Kind()
if kind >= reflect.Chan && kind <= reflect.Slice {
// ...
}
- 用
%+v
来打印数据的比较全的信息 - 注意空结构
struct{}
, 看 issue: https://github.com/golang/go/issues/23440
func f1() {
var a, b struct{}
print(&a, "\n", &b, "\n") // Prints same address
fmt.Println(&a == &b) // Comparison returns false
}
func f2() {
var a, b struct{}
fmt.Printf("%p\n%p\n", &a, &b) // Again, same address
fmt.Println(&a == &b) // ...but the comparison returns true
}
包装错误: http://github.com/pkg/errors
- 例如:
errors.Wrap(err, "additional message to a given error")
- 例如:
在 Go 里面要小心使用
range
:for i := range a
andfor i, v := range &a
,都不是a
的副本- 但是
for i, v := range a
里面的就是a
的副本 - 更多: https://play.golang.org/p/4b181zkB1O
从 map 读取一个不存在的 key 将不会 panic
value := map["no_key"]
将得到一个 0 值value, ok := map["no_key"]
更好
不要使用原始参数进行文件操作
- 而不是一个八进制参数
os.MkdirAll(root, 0700)
- 使用此类型的预定义常量
os.FileMode
- 而不是一个八进制参数
不要忘记为
iota
指定一种类型
const (
_ = iota
testvar // testvar 将是 int 类型
)
vs
type myType int
const (
_ myType = iota
testvar // testvar 将是 myType 类型
)
当前内容版权归 cristaloleg 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 cristaloleg .