基础特性
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,但性能一般。
非线程安全。如何并发读写,stackoverflow
for range遍历顺序随机(常见于CPU负载高时)。因此业务逻辑一定不能依赖遍历顺序。官方解释有意设计成随机。
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