当前位置:首页 > 文章列表 > Golang > Go教程 > Go gojq 怎样取消仍在计算的查询

Go gojq 怎样取消仍在计算的查询

来源:17golang原创 2026-10-30 23:04:13 0浏览 收藏

Go gojq 要取消仍在计算的查询,应把可取消的 context 传入 code.RunWithContext(ctx, input) 或 query.RunWithContext(ctx, input)。执行期间取消上下文,迭代器会返回对应的 context 错误。需要检查 Next 返回值是否为 error;只在外层超时后停止等待,不能让未接收上下文的查询自动结束。

官方地址:https://github.com/itchyny/gojq

区分停止等待与停止计算

设想一个提供 JSON 查询的服务:请求已超时,处理协程却仍卡在 iter.Next()。如果只用 select 让请求函数返回,查询所在协程可能继续计算。并发请求增加后,这些遗留计算仍然占用资源,外层超时数字并不代表内部任务已经停止。

还有一种容易漏掉的情况:在每次 Next 之前检查 ctx.Err(),但 Next 本身长期不返回。对于没有中间输出的复杂或无限查询,循环外的检查没有机会再次运行。因此取消信号必须传到 gojq 自身的执行环境,而不能仅停留在消费循环中。

把上下文绑定到查询执行

先 Parse 得到 Query,再 Compile 为 Code;执行阶段调用 RunWithContext,为每次任务创建自己的迭代器。来自 HTTP 请求的 r.Context() 可以作为父上下文,再用 WithTimeout 收紧单次查询预算。父请求取消也能传播到子上下文。

gojq查询执行与上下文的静态关系
静态结构图:请求分组关联父上下文和预算上下文,查询分组包含 Code、RunWithContext 与迭代器;连线表示依赖,不是时间轴。

复用同一查询的 Code 可以避免重复编译,但每次执行仍需要新的上下文和迭代器。本文不共享可变输入,也不在多个协程中并发调用同一个 Iter.Next。相关入口见Code.RunWithContext 官方文档。

在迭代器中处理取消错误

下面的 CollectLimited 接收已经编译好的 Code,为执行设置 250 毫秒预算,并限制结果数量。出错时返回 nil,明确丢弃已收集的部分结果。示例用持续归约的查询说明:即使没有中间值可取,也必须让计算本身收到取消信号。

package main

import (
    "context"
    "errors"
    "fmt"
    "time"

    "github.com/itchyny/gojq"
)

// CollectLimited 接收已编译查询;出错时丢弃部分结果。
// 上下文约束查询执行,不包含调用前的 Parse、Compile。
func CollectLimited(parent context.Context, code *gojq.Code,
    input any, limit int) ([]any, error) {
    if code == nil || limit = limit {
            return nil, fmt.Errorf("查询结果超过上限 %d", limit)
        }
        values = append(values, value)
    }
}

func main() {
    // 示例查询持续计算归约值,不产生可提前消费的中间结果。
    query, err := gojq.Parse("reduce range(0; infinite) as $k (0; . + 2)")
    if err != nil {
        panic(err)
    }
    code, err := gojq.Compile(query)
    if err != nil {
        panic(err)
    }
    _, err = CollectLimited(context.Background(), code, nil, 8)
    switch {
    case errors.Is(err, context.DeadlineExceeded):
        fmt.Println("查询预算已耗尽")
    case errors.Is(err, context.Canceled):
        fmt.Println("上游取消查询")
    case err != nil:
        panic(err)
    }
}

250 毫秒是演示预算,不是保证函数恰在这一时刻返回。错误通过 %w 包装,所以入口可以用 errors.Is 区分 DeadlineExceeded 与 Canceled。这里按首个执行错误终止,是应用选择;不要把所有 gojq 执行错误都改写成超时。

这个示例没有在本文环境执行,所述取消行为来自官方接口与实现。部署时应按实际输入、查询表达式及业务预算配置超时,不把演示时长照搬为统一标准。

说明服务层并发与资源边界

RunWithContext 是协作式取消。当前执行器在解释执行循环中检查 ctx.Done,并将 ctx.Err 作为错误值返回;它不会强制抢占任意 Go 代码。自定义函数、输入迭代器或其他扩展如果在一次调用里阻塞很久,需要自己有退出机制,不能假设解释器能够打断它。可参考执行器的上下文处理。

迭代错误、扩展调用与资源限制的关系
静态结构图:执行器关联取消错误,扩展调用关联独立退出机制,结果数量关联收集内存;说明各层职责,不是性能数据。

Parse、Compile、输入 JSON 解码与结果序列化,也不因把 ctx 传给 RunWithContext 就自动获得相同的可中断能力。生产服务应分别控制输入大小、表达式来源、执行并发和输出体积。结果条数上限只能约束已产生的值,不能限制某一个巨大结果的内存占用。

不必为了使用上下文额外为每次 Next 启动协程。先让 gojq 执行环境感知取消,再决定服务层如何调度任务。若查询仍长期不返回,应检查是否停在扩展调用、输入等待或单次耗时操作,而不是继续叠加只会停止等待的超时包装。

层次本文措施仍需关注
执行计算RunWithContext协作式检查与扩展调用
请求生命周期父 context 与单任务超时是否丢失父取消信号
结果收集条数上限单个结果大小
并发任务每次独立迭代器服务端并发预算与共享数据

处理部分结果及常见问题

流式查询可能先给出部分值,再超时。接口要明确这些值能否交付:本文选择出错即丢弃,适合需要完整结果的调用;若服务允许部分结果,则应同时返回明确的未完成状态,不能只输出已有数组而伪装成完整成功。

观察执行耗时、取消错误数量、活跃查询数、结果体积和超时后任务是否回落,有助于判断取消是否真正传到了执行层。这里提供观察项,不声称已经取得线上改善或吞吐提升。

创建了 WithTimeout,却还在用 Run,可以取消吗?不能仅靠创建上下文实现取消,必须把该上下文传入 RunWithContext。

Next 的 ok 为 true 就是正常数据吗?不是。error 也可能以迭代值出现,需先做类型判断,再处理正常结果。

只要限制结果条数就能限制计算吗?不能。有些查询长时间没有输出,条数限制无从触发;执行预算与结果限制应配合使用。

取消后要再次执行怎么办?使用新的上下文和新的迭代器启动任务。不要复用已取消的上下文,也不要把旧迭代器当成可重新开始的查询。

将请求上下文传到执行入口,读取并分类迭代错误,再明确扩展调用和部分结果的处理职责,才能让“请求不再等待”对应到可控的查询生命周期。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go go-flags 的 optional 与 optional-value 有什么区别Go go-flags 的 optional 与 optional-value 有什么区别
上一篇
Go go-flags 的 optional 与 optional-value 有什么区别
Go gojq 的 input 为什么需要单独提供输入迭代器
下一篇
Go gojq 的 input 为什么需要单独提供输入迭代器
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    799次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    792次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    877次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    848次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    680次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码