下面是代码示范;
实现背景: 去promotheus中获取不同的数据,并api接口返回数据。
我所考虑的问题:
- error的处理
- goroutine的控制
- 代码的优雅和冗余性
- 后续新需求的可拓展性
第一: error的处理
在这一段代码中, 需要对每一个调用service层可能出错的error进行捕捉,并返回给用户error信息.所以我用了 有缓冲的队列:errCh来接收error信息。
第二: goroutine的控制
控制并发数量,使用channel来控制并发数量,使用 sync.waitGroup来确保程序的阻塞。
func (w *dashboardWeb) GetViewData(ctx *gin.Context) (interface{}, error) {
var (
errCh = make(chan error, 15)
result = model.DashboardViewResModel{}
taskCount = 15
ch = make(chan func(), 4)
wg = sync.WaitGroup{}
)
StartTime := cast.ToInt64(ctx.Query("startTime"))
EndTime := cast.ToInt64(ctx.Query("endTime"))
Granularity := cast.ToInt(ctx.Query("granularity"))
fns := []func(){
func() {
data, err := w.ListAz()
if err != nil {
errCh 0 {
go func() {
defer wg.Done()
for fn := range ch {
fn()
}
}()
taskCount--
}
for _, fn := range fns {
ch
核心代码分析和引发的思考。
for taskCount > 0 {
go func() {
defer wg.Done()
for fn := range ch {
fn()
}
}()
taskCount--
}
for _, fn := range fns {
ch
上面的代码的写法我个人感觉比较优雅,它应用了golang的channel,使用了生产者消费者模型。
fns是一个匿名函数的列表, fn是一个一个的执行动作。
将每个执行动作(fn) 生产到我们定义的ch channel中即可
从上述的例子中,可以思考下,golang的生产者消费者模型?
生产者:发送数据端
消费者:接收数据端
为什么需要有缓冲区?
1.解耦(降低生产者与消费者之间的耦合度)当消费者发生变化时,不会直接影响到生产者。
2.并发。n个消费者可以先写入缓冲区,再由消费者读出。生产者和消费者数量不等时,能保持正常通信。
3.缓存数据:当生产者和消费者数据处理速度不一致时,暂存数据
![Go入门:并发的写法(通过生产消费者模型)](http://cdn.xkd.club/wp-content/uploads/2022/06/frc-887a0c972fb2d549abff2d9e519bbea6.png)
image.png
例如:
package main
import (
"fmt"
)
func producer(out chan