基础特性
Go
Why Use Go
编译快(语法简单)
启动快,占用内存小(无运行时)
部署快(docker/k8s支持好)
容易编写高并发(goroutine等)、网络服务(官方网络通信库、序列化库、加解密等)
内置工具丰富(CGO/Unit Test/Benchmark/pprof/template/...)
强类型,但支持duck-typing这种动态语言的能力
Type
值类型:
built-in
,array
,struct
引用类型:
slice, map, channel, interface, function
无
enum
, 通过const+iota
模拟无
class
,只有值类型struct
无继承,通过
type embedding
模拟无多态,通过将子类型真实对象传入父类型保存下来,显式调用真实对象的函数
鸭子类型,但必须结合
interface
使用无法显式实现某个
interface
解决方案(如果没有实现会报错)。
var _ IMyInterface = (*MyType)(nil)
interface{}
fmt.Sprintf(%T, a)
cat, ok := animal.(Cat)
这种用法非常常见,注意有时判断ok还不够swtich t:= animal.(type)
reflect.TypeOf(a)
slice
引用类型,可以为
nil
只占用3个指针大小(不含数据存储): 指向底层数组容器、长度、容量
建议初始化时长度等于容量
自动动态扩容(实际存储的array会发生变化,尤其注意)
slicing规则
s[:i]
返回第i个元素以前(不含s[i]
)的切片。s[i:]
返回第i个元素及以后(含s[i]
)的切片。
map
基于HashMap,但性能一般。
struct
无法显式声明实现某个interface。
无继承,通过组合实现封装、代码复用。为此还提供两个语法糖:
anonymous field
和promoted field
。没有成员函数,而使用function with receiver 来模拟成员函数。
interface
go的interface本身也是一个对象,这个对象包含两个指针,分别指向实际对象、实际对象类型的方法表。这个设定的好处是实现动态语言般的
duck typing
,坏处是给判空带来额外的复杂性。
interface{}
可以接收任意类型。
更多资料
https://halfrost.com/go_interface/
https://zhaolion.com/post/golang/upgrade/interface/
https://github.com/teh-cmc/go-internals/blob/master/chapter2_interfaces/README.md
channel
No-buffer channel: 收发端需要同时准备好,否则阻塞。
Buffered (Queue) channel. 当channel空时接收端阻塞,当channel满时发送端阻塞。
只读型
<-chan
, 只写型chan<-
可用于同步
需要手动关闭
close(c)
, 而不是通过发送nil
Reflection
https://halfrost.com/go_reflection/
Variable
大小学决定package外的可见性
自带gc,使用静态逃逸分析决定变量在堆还是在栈上,无法人工控制。
new(T)
只分配内存并清零。返回一个*T
对象(指针)。简化写法&T{}
。make
只用于slice, map, channel
Control flow
switch-case-fallthrough
select-case-channel
panic-recover
defer 离开当前scope时执行,多个defer按照LIFO(栈)顺序执行
goroutine
goroutine类似协程,是逻辑概念,由go调度。
goroutine和线程没有从属关系,不同goroutine可能分布在不同线程里。
需要注意多线程race-condition:通过
go build -race
检测。必要时使用
atomic
,sync.Mutex
等操作共享数据。常常使用
channel
起到同步和共享数据的作用。
新建一个goroutine很简单,在普通函数调用前加
go
即可。
concurrency
专门讨论基于goroutine的并发和同步。
简单情况下,使用channel即可同步。
使用
sync.WaitGroup
。使用
Context
管理复杂情况。多层级或一组关联的goroutine(尤见于web server)。 https://pkg.go.dev/context
Tool
go build
go test
go run race MyTest.go 检查goroutine是否有竞态
go run -gcflags "-m -l" .MyTest.go 检查是否有逃逸
go tool pprof
go generate
text template
Compiler Tag
go没有宏,但可以通过
+build [tag1, tag2, ...]
条件编译。支持多个tag(&&)。支持内置tag如linux, arm64,支持自定义tag(通过go build -tags ...
指定)//go:inline
建议内联,//go:noinline
强制不内联go build -ldflags "-s -w"
可以让编译出的包更小(因为剥离了符号表),也更加安全。
Last updated