跳到主要内容

go 语言你不知道的那些事

· 阅读需 5 分钟
ahKevinXy

CDC

change data capture

key 被更新的时候打印数据

开源框架选择合适的组件

e2e测试

责任链模式

不同的Handler 组成一条链,链条上的每一个环都有自己功能.一方面可以用责任链模式将复杂逻辑分成链条上的不同步骤

洋葱模式

拥有一个核心,这个核心一般是业务逻辑.而后在这个核心外层层面包裹,每一层就是一个middleware.一般用洋葱模式来无侵入式地增强核心功能,或者解决AOP问题

AOP

AOP是面向切面编程,用于解决横向关注点问题,如可观察性问题,安全问题等

sync Cond

使用场景

有一个协程正在接受数据,其它协程必须要等待这个协程接收数据完成,才能读取正确的协程

  • 可以用一个全局变量标识第一个协程是否接收数据完成,剩下的协程反复检查该变量的值,直到读取到数据
  • 也可以创建多个channel ,每个协程阻塞在一个channel上,由接收数据的协程在数据接收完毕后,挨个通知

哪些方法

NewCond 创建实例

Broadcast 广播唤醒所有

Signal 唤醒一个协程

Wait 等待

go context 应用

Context 解读


type Context interface {
Done() <-chan struct{}
Err() error
Deadline()(dealine time.Time,ok bool)
Value(key any) any
}

Context 是一个接口,定义了四个方法,他们都是幂等

Done() 返回一个channel 可以表示context 被取消的信号 当这个channel被关闭时 说明context被取消了,这是一个只读的channel 读一个关闭的channel会读出相应类的零值,并且源码里没有地方会向这个channel里面塞值,因此在子协程里读这个channel 除非被关闭否则读出不了任何东西.当子协程从channel读出了值后,就可以做出收尾工作,尽快退出

Err() 返回一个错误,表示channel 被关闭的原因 例如是被取消 或者超时 Dealine() 返回context的截止时间,通过此时间,函数就可以决定接下来的操作.如果时间太短,就可以不往下做了,浪费系统资源,也可以用这个dealine 来设置一个I/O操作的超时时间

Value() 获取之前设置的key对应的值

canceler

type canceler interface{
cancel(removeFormParent bool,err error)
Done() <-chan struct
}

实现意思定义的两个方法,就表明该 Context是可以被取消的

请求requestId 链路




go channel 应用

停止信号

任务定时

timer结合


select {
case <-time.After(100*time.Millisecond)
case <- s.stopc:
return false
}

定时执行任务

package main

func worker() {
ticker := time.Tick(1*time.Secend)

for {
select {
case <-ticker:
fmt.Println("执行了1s ")
}
}
}

解耦生产方和消费方

控制并发数

同时执行几百个任务 如何在任务执行过程中,对频率进行限制

package main


var limit = make(chan int,3)

func main(){

for _,w:=range work {
go func() {
// 超过三个为执行完成 一直等待
limit <-1
w()
<-limit
}()
}
}

构建缓冲型的channel,容量为3 接这遍历任务列表,每个任务启动一个goroutine去完成.真正执行任务,访问第三方的动作再w()中完成 在执行w()之前,先要从limit 中拿许可证,拿到许可证之后,才能执行w(),等任务完成后归还,

limit <- 在func 内部的原因

如果在外层,就是控制系统goroutine的数量,可能会阻塞for 循环,影响业务逻辑 limit 其实和逻辑无光,只是性能调优,放在内层和外层语义不一样

需要 defer 来保障