GO语言是一门函数式编程的语言。写起来有不一样的味道。
GO语言是一门静态类型语言,使用变量的时候需要预先声明。
GO语言没有类,但是可以用结构体来模拟类的一些特性。
GO语言适合写服务,写逻辑的能力有待考察。
GO语言跟其他语言的通信用gRPC的方式还是用httpAPI的方式有待考察。
GO编码规范,https://golang.org/doc/effective_go.html

运行态 runtime

  • 获取当前goroutine数量 num := runtime.NumGoroutine()

一些库

交叉编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 如果你想在Windows 32位系统下运行
$ CGO_ENABLED=0 GOOS=windows GOARCH=386 go build test.go

# 如果你想在Windows 64位系统下运行
$ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go

# 如果你想在OS X 32位系统下运行
$ CGO_ENABLED=0 GOOS=darwin GOARCH=386 go build test.go

# 如果你想在OS X 64位系统下运行
$ CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build test.go

# 如果你想在Linux 32位系统下运行
$ CGO_ENABLED=0 GOOS=linux GOARCH=386 go build test.go

# 如果你想在Linux 64位系统下运行
$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build test.go

一些开发实践

异常处理统一使用error,不要使用panic/recover来模拟throw…catch,最初我是这么做的,后来发现这完全是自以为是的做法。

原生的error过于简单,而在实际的API开发过程中,不同的异常情况需要附带不同的返回码,基于此,有必要对error再进行一层封装。

任何协程逻辑执行体,逻辑最开始处必须要有defer recover()异常恢复处理,否则goroutine内出现的panic,将导致整个进程宕掉,需要避免部分逻辑BUG造成全局影响。

在Golang中,变量(chan类型除外)的操作是非线程安全的,也包括像int这样的基本类型,因此并发操作全局变量时一定要考虑加锁,特别是对map的并发操作。

所有对map键值的获取,都应该判断存在性,最好是对同类操作进行统一封装,避免出现不必要的运行时异常。

定义slice数据类型时,尽量预设长度,避免内部出现不必要的数据重组。