错误处理
基础语法 —— 错误处理
- error:一般用于表达可以被处理的错误
- error只是一个内置的接口
- panic:一般用于表达非常严重不可恢复的错误
基础语法 —— errors 包
- New 创建一个新的 error
- Is 判断是不是特定的某个error
- As 类型转换为特定的 error
- Unwrap 解除包装,返回被包装的 error
基础语法 —— error 和 panic 选用哪个?
- 遇事不决选 error
- 当你怀疑可以用 error 的时候,就说明你不需要 panic
- 一般情况下,只有快速失败的过程,才会考虑panic
基础语法 —— 从 panic 中恢复
- 某些时候,你可能需要从 panic 中恢复过来:比如某个库,发生 panic 的场景是你不希望发生的场景。这时候,你需要我们的 recover
Tip:如果你自己panic了,然后又要恢复过来,那么应该考虑不要用panic了
Golang 语法 —— defer
- 用于在方法返回之前执行某些动作
- 像栈一样,先进后出
- defer 语义接近 java 的 finally 块,所以我们经常使用 defer 来释放资源,例如释放锁
Golang 语法 —— 闭包
- 函数闭包:匿名函数 + 定义它的上下文
- 它可以访问定义之外的变量
- Go 很强大的特性,很常用
Golang 语法 —— 闭包延时绑定
- 闭包里面使用的闭包外的参数,其值是在最终调用的时候确定下来的
要点总结
- error 其实就是一个内置的普通的接口。error 相关的操作在 errors 包里面
- panic 强调的是无可挽回了。但是也可以用 recover 恢复过来
- 闭包是很强大的特性,但是要小心延时绑定
AOP设计——责任链模式
- 为 server 支持一些 AOP 逻 辑
- AOP:横向关注点,一般用于解决 Log, tracing,metric,熔断,限流等
- filter:我们希望请求在真正被处理之前能够经过一大堆的 filter
要点总结
- 责任链是很常见的用于解决 AOP 的一种方式。
- 类似的也叫做 middleware, interceptor… 本质是一样的
- Go 函数是一等公民,所以可以考虑用闭包来实现责任链
- filter 很常见,比如说鉴权,日志,tracing,以及跨域等都可以用 filter 来实现
sync 包
基础语法 —— sync.Map
- key 和 value 类型都是interface{}。意味着你要搞各种类型断言
基础语法 ——类型断言
形式:t, ok := x.(T) 或者 t := x.(T)
T 可以是结构体或者指针
如何理解?
即x是不是T;类似Java instanceOf + 强制类型转换合体。如果 x 是 nil,那么永远是 false
编译器不会帮你检查
基础语法 ——类型转换
- 形式:y := T(x)
- 如何理解?记住数字类型转换,string 和 []byte 互相转
- 类似Java强制类型转换
- 编译器会进行类型检查,不能转换的会编译错误
基础语法 —— sync.Mutex 和 sync.RWMutex
sync 包提供了基本的并发工具
- sync.Map:并发安全 map
- sync.Mutex:锁
- sync.RWMutex:读写锁
- sync.Once:只执行一次
- sync.WaitGroup: goroutine 之间同步
基础语法 —— mutex家族注意事项
- 尽量用 RWMutext
- 尽量用 defer 来释放锁,防止panic没有释放锁
- 不可重入:lock 之后,即便是同一个线程(goroutine),也无法再次加锁(写递归函数要小心)
- 不可升级:加了读锁之后,如果试图加写锁,锁不升级
基础语法 —— sync.Once
要点总结
- 尽量用 sync.RWMutex
- sync.Once 可以保证代码只会执行一次,一般用来解决一些初始化的需求
- sync.WaitGroup 能用来在多个 goroutine 之间进行同步