从Prometheus查询数据后,将每个值除以bet参数,然后返回计算结果
一.需求有一个函数 endUrlPrometheus它接收一些参数来构建一个查询Prometheus的URL然后发送GET请求,返回的是一系列数据点每个点包括一个时间戳和该时间戳上的值,然后可以对这些数据进行进一步的处理例如取平均值、最大值等二.代码如下import ( encoding/json fmt net/url strconv ) // 定义Prometheus响应结构 type PrometheusResponse struct { Data struct { Result []struct { Values [][]interface{} json:values // [[时间戳, 值],...] } json:result } json:data } func SendUrlPrometheus(curlPrometheus, query string, from, to int64, step, bet int32) ([]interface{}, error) { // 构造请求URL promURL : fmt.Sprintf( http://%s:9090/api/v1/query_range?query%sstart%dend%dstep%d, curlPrometheus, url.QueryEscape(query), from, to, step, ) // 发送GET请求 data : util.SendUrl(promURL, get) // 如果bet为0避免除零错误 if bet 0 { return nil, fmt.Errorf(bet参数不能为0) } betFloat : float64(bet) // 解析Prometheus响应 var promResp PrometheusResponse if err : json.Unmarshal(data, promResp); err ! nil { return nil, fmt.Errorf(解析Prometheus响应失败: %w, err) } if len(promResp.Data.Result) 0 { return []interface{}{}, nil // 无数据返回空切片 } // 处理结果每个值除以bet result : make([]interface{}, 0, len(promResp.Data.Result[0].Values)) for _, point : range promResp.Data.Result[0].Values { if len(point) ! 2 { continue // 跳过无效数据点 } // 提取时间戳 timestamp, ok : point[0].(float64) if !ok { continue // 时间戳格式无效 } // 提取值并转换为浮点数 var value float64 switch v : point[1].(type) { case string: // 尝试转换字符串数值 if val, err : strconv.ParseFloat(v, 64); err nil { value val } else { continue // 转换失败跳过 } case float64: value v case int: value float64(v) default: continue // 不支持的类型 } // 执行除法运算值 / bet calculatedValue : value / betFloat // 保留两位小数可选 // calculatedValue math.Round(calculatedValue*100) / 100 // 添加到结果集时间戳转换为int64 result append(result, []interface{}{ int64(timestamp), calculatedValue, }) } return result, nil }// 示例调用代码 func main() { // 假设的请求参数 gameId : 123 bet : int32(4000) curlPrometheus : prometheus.example.com from : time.Now().Add(-1*time.Hour).Unix() to : time.Now().Unix() step : int32(60) // 构造查询 query : fmt.Sprintf( sum by (game_id, bet) (game_data{game_id%d,bet%d}), gameId, bet, ) // 调用函数 result, err : SendUrlPrometheus(curlPrometheus, query, from, to, step, bet) if err ! nil { panic(err) } // 处理结果 for i, item : range result { point : item.([]interface{}) timestamp : point[0].(int64) value : point[1].(float64) fmt.Printf(点 %d: 时间 %s, 值/%.2f %.4f\n, i1, time.Unix(timestamp, 0).Format(time.RFC3339), float64(bet), value, ) } }三.关键特点安全除法在计算前检查bet是否为零避免除零错误使用float64计算保证精度灵活的类型处理处理Prometheus返回的不同数值类型string/float64/int兼容多种时间戳格式错误处理跳过无效数据点长度不足/类型错误/转换失败当无结果时返回空切片而非nil性能优化使用带容量的切片减少内存分配最小化类型转换开销精度控制提供注释的代码可以四舍五入到两位小数四.输出示例Prometheus返回[[1692928800, 5140745], [1692929100, 5140745]]