惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Security Affairs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
大猫的无限游戏
大猫的无限游戏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
爱范儿
爱范儿
阮一峰的网络日志
阮一峰的网络日志
GbyAI
GbyAI
D
Docker
美团技术团队
N
Netflix TechBlog - Medium
罗磊的独立博客
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Hugging Face - Blog
Hugging Face - Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Jina AI
Jina AI
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
腾讯CDC
MongoDB | Blog
MongoDB | Blog
Last Week in AI
Last Week in AI
博客园 - 三生石上(FineUI控件)
博客园 - 叶小钗
V
V2EX
L
LangChain Blog
博客园 - 【当耐特】
B
Blog RSS Feed
量子位
U
Unit 42
Engineering at Meta
Engineering at Meta
小众软件
小众软件
宝玉的分享
宝玉的分享
H
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
云风的 BLOG
云风的 BLOG
博客园 - 聂微东
博客园 - 司徒正美
The Cloudflare Blog
The GitHub Blog
The GitHub Blog
T
Tailwind CSS Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
The Last Watchdog
The Last Watchdog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
SegmentFault 最新的问题
博客园_首页
Attack and Defense Labs
Attack and Defense Labs
TaoSecurity Blog
TaoSecurity Blog
Apple Machine Learning Research
Apple Machine Learning Research
S
Security @ Cisco Blogs

Go 编程语言

[工业边缘网关] EdgeX 更新啦 上线了官网 顺便更新版本 v0.10.0 - V2EX 有了 Agent,后台脚手架是该退场,还是变成约束层? - V2EX 强兼 Claude Code:左 DeepSeek V4,右 Kimi K3 - V2EX 构建时自动注入版本号:从 Git tag 到 Go 可执行文件 - V2EX [边缘计算] 想借助 AI 来开发 边缘网关接入 AI 解决设备通信 不知道有没有需求 - V2EX [Go]工业边缘计算网关 edgex 业余时间独立开发 持续更新半年咯 求个 star - V2EX eget:不用等中央仓库,直接安装 GitHub 和任意下载站的工具 - V2EX gookit/gcli v3.8:新增支持共享选项、文档生成和参数重排 - V2EX V2EX 我开源了一款极简的 P2P 文件传输与 VPN 工具 (Win/Mac/ Linux /Android) - V2EX 用 Go gRPC 信令对接 Android WebRTC:大家一般怎么划分网关和客户端边界? 在服务端用 Pion + FFmpeg + RNN 做 WebRTC 通话降噪,值得吗? 这两种 lint 报错场景, v 友们一般怎么处理 - V2EX tikrok 的部分来时路 tikrok 第 7 代微服务重构: Golang 微服务 grpc 接口与服务实现隔离方案 写了个 Go 库:在 TCP 应用协议开始前做认证,也支持端口敲门 Tikrok v6.0 新的生产级架构,成本不变,但是部署复杂略有增加 go 打包的二进制程序怎么反编译 [边缘计算开源] 工业数据采集网关 版本更新 用 golang 写了,一套面向个人音乐资产的本地优先音乐系统 做了个 Go 的 MCP Server 框架,一行代码把 Gin API 接入 AI - V2EX 写了个 Go 库解决 LLM 流式输出断线重连的问题 - V2EX Tikrok v5.0 新的的底层实现 - V2EX OpenTelemetry 分布式追踪中的回溯采样:削减 60% 尾部采样成本 - V2EX 求推荐一个 go 里运行 js 的方案 - V2EX [边缘计算] 基于 GO 的采集网关持续更新啦 - V2EX [边缘计算开源] 基于 go 写了个独立运行的工业数据采集网关 后续阶段应该如何调整 - V2EX 然后 go-kratos 不怎么活跃了,连最火的 skills 都不搞, github 也没什么人回复了 - V2EX Excelize 开源基础库发布 2.10.1 版本更新 phper 转 go 最好的 web 框架是 goframe 吗? - V2EX A Visual Studio Code extension that displays the disk size of Go module dependencies in go.mod files. - V2EX miglite: Go 极简高效的数据库迁移工具 - V2EX 每秒万级 Tick 震荡:高频行情分发,该选 Golang 的并发原生还是 Rust 的极致性能? - V2EX 给 netcat 引入了 P2P 穿透、多路复用、强加密以及内置服务模块,并且完全开源 - V2EX 使用 "go.inlayHints.parameterNames": true 在 vscode 中开启类似 goland 的参数提示 - V2EX 下面代码中 f()会被重复执行吗?大佬帮忙解答一下~ - V2EX sublimetext 开发 GO 使用体验怎么样 - V2EX [开源] 将 react 的 hooks 和 组件化思路带入 go 的 TUI 开发。 - V2EX gocar 0.2.0 版本:新增自定义命令功能,实现真正的 go 的 cargo - V2EX go 新手,求问导入包失败问题 - V2EX 之前写的, JSR-310 风格的时间日期库, 1.0 了 - V2EX 为了方便学习 go, 使用 go 做了一个命令行版本的 go playground, 代码直接一键运行, 一键编译 - V2EX 虚心请教 Go 前辈们,关于入行 - V2EX 关于 Go 的工程经验 - V2EX 微信开发框架开源,基于 Go+Wails3+React - V2EX Golang 实现的开源 NVR 支持 GB28181 & ONVIF 啦 - V2EX Go 工具库 gookit/goutil v0.7.2 发布:增强功能与修复,提升开发体验 - V2EX go-carbon v2.6.15 正式版发布,已被 docker 官方组织使用 - V2EX 如何用 3–5 个高效问题快速识别 Golang 开发者的技术素养? - V2EX 有没有 go 的 ai 应用项目学习学习 - V2EX Go 环境版本管理用哪个- -有点疑惑 - V2EX Goland 下的通义千问不能选择模型,VScode 下面的通义千问可以选择模型 - V2EX 新手入门求指导 - V2EX 看 Go 的时间库不顺眼很久了,所以从别的语言里抄了一个 - V2EX go-dongle v1.2.0 发布,新增 SM2 非对称椭圆曲线加密算法支持 - V2EX Wails2+Vue3 本地的绑定文件和 Vite 上的不一致 - V2EX go 返回错误的时候, 返回的值应该可用吗 - V2EX Go 入门基础课(2025 Golang) - V2EX goland 中如何 debug wails - V2EX 日期函数获取上一个月 bug, 在一些特殊日子才出现,比如今天 10-31 - V2EX go-carbon v2.6.14 发布,一个轻量级、语义化的 golang 时间处理库 - V2EX goroutine 到底算不算一种 coroutine 的实现? - V2EX 为什么不用 gRPC-Go: VictoriaTraces 中实现 OTLP/gRPC 的幕后故事 - V2EX go 最新版的 map 并发读是安全的吗。 - V2EX 请问一下 golang 下有什么成熟稳定的串口通讯包? - V2EX golang.org/x/sync/syncmap 被 struct 裹挟时 使用前为什么必须为每个键初始化 不然取值得到 nil go-dongle v1.1.7 发布,新增 SM4 国密分组对称加密算法支持 在开发接口的过程中,如何快速验证结果? - V2EX go-carbon v2.6.13 发布,一个轻量级、语义化的 golang 时间处理库
gookit/gcli v3.5.0 发布 - 简单易用、功能丰富的 Go 命令行应用与工具库 - V2EX
jxia · 2026-06-23 · via Go 编程语言

gookit/gcli 是一个用 Go 编写的命令行应用与工具库。 本文汇总了从 v3.3.1 到最近发布的 v3.5(包含 v3.4 周期)的主要改动。这次更新主要集中在开发体验优化和底层健壮性修复上。

如果你在用 Go 写 CLI 工具,这次更新里有几个比较实用的功能。下面直接看重点。

核心更新概览

  • Shell 自动补全:支持零注册生成及动态补全模式( bash / zsh / PowerShell )。
  • 命令中间件:通过 Command.Use() / App.Use() 处理鉴权、日志等通用逻辑。
  • 帮助信息分组:使用 Category 对命令和选项进行分类展示。
  • 结构体绑定优化:新增 field 标签规则,支持匿名嵌套结构体自动展开。
  • 交互式收集:缺值时可通过 Question 自动提示输入。
  • POSIX 短选项合并:支持 -aux 拆分为 -a -u -x
  • 健壮性修复:panic 处理优化、help 命令行为修正等。
  • 少量破坏性变更(文末附迁移指南)。

1. Shell 自动补全改进

以前生成补全脚本需要硬编码命令和选项,新增命令后得重新生成。从 v3.5 开始,GCli 改进了这一流程。

不需要再手动注册 genac 命令,直接使用内置全局选项即可生成静态脚本:

# 为你的 shell 生成补全脚本,然后 source 它
myapp --gen-completion bash > myapp.bash
source myapp.bash

# zsh / PowerShell 同样支持
myapp --gen-completion zsh  > _myapp
myapp --gen-completion pwsh > myapp.ps1

此外,新增了动态补全模式。默认生成的脚本不再硬编码名称,而是在补全时通过内置的 --in-completion 选项动态调用你的程序获取候选项。以后新增命令,Tab 补全立即生效。

对于选项的取值,也可以通过 Choices 设置候选列表:

c.StrOpt2(&format, "format", "output format",
    gflag.WithChoices("json", "yaml", "table"))
// 输入 `--format <Tab>` 会提示: json  yaml  table

2. 命令中间件

如果需要在执行命令前做鉴权或记录日志,又不想把代码塞进每个命令里,可以使用中间件。

通过 Use() 注册的处理器会按顺序在命令主函数 Func 之前执行。如果某个处理器返回 error ,执行链会中止,错误向上传递。

// 命令级中间件
cmd.Use(func(c *gcli.Command, args []string) error {
    if os.Getenv("TOKEN") == "" {
        return c.NewErrf("missing TOKEN env")
    }
    return nil // 返回 nil 继续执行链
})

// 应用级中间件:在每个命令执行前生效
app.Use(func(c *gcli.Command, args []string) error {
    gcli.Debugf("running command: %s", c.Name)
    return nil
})

Command.Use()App.Use() 都返回接收者本身,支持链式调用。未使用中间件的代码行为与之前完全一致。

3. 帮助信息分组

当应用的命令和选项变多时,帮助信息会显得杂乱。现在可以通过设置 Category 字段将它们归类到带标题的分组中。

// 命令分组
app.Add(&gcli.Command{Name: "migrate", Desc: "run db migrate", Category: "database"})
app.Add(&gcli.Command{Name: "serve",   Desc: "start http server"}) // 默认分组

// 选项分组
cmd.StrVar(&dsn, &gcli.CliOpt{Name: "db-dsn", Desc: "database dsn", Category: "database"})
cmd.StrOpt2(&port, "port", "bind port", gflag.WithCategory("network"))

分组按首次出现的顺序排列,组内条目按名称排序。未设置分类时,输出格式与旧版相同。

4. 结构体绑定优化

FromStruct 新增了第三种标签规则(TagRuleField),并支持自动展开匿名嵌套结构体。

现在支持的三种规则:

  • gcli.TagRuleNamed(默认):flag:"name=int0;shorts=i;required=true;desc=message"
  • gcli.TagRuleSimpleflag:"desc;required;default;shorts"
  • gcli.TagRuleField(新增):使用字段名的 SnakeCase 作为选项名,元数据从独立的 tag 键读取。
type commonOpts struct {
    Verbose bool `flag:"v" desc:"enable verbose output"`
}

type demoOpts struct {
    commonOpts        // 匿名嵌套:展开为 --verbose/-v 选项
    UserName string `flag:"u" desc:"the user name" required:"true"`
    Age      int    `desc:"the user age" default:"18"`
}

c.MustFromStruct(&demoOpts{}, gcli.TagRuleField)
// => 选项: --user-name/-u (必填), --age (默认 18), --verbose/-v

field 规则的好处是选项名直接取自字段名,descdefault 等属性各自独立成键,可读性更好。

5. 声明式交互收集

如果某个选项必填但用户没传,可以挂载一个 Question。GCli 会在检测到空值时交互式提示输入。

c.StrOpt2(&token, "token", "the access token",
    gflag.WithQuestion("Please input your access token: "))

运行效果:

$ myapp deploy
Please input your access token: ▮

如果同时设置了自定义 Collector,则 Collector 逻辑优先。

6. POSIX 短选项合并

支持了 -a -u -x 合并写成 -aux 的 POSIX 风格。该功能默认关闭,需要通过 Config.EnhanceShort 手动开启。

c.ParserCfg().EnhanceShort = gcli.EnhanceShortMerge  // 1: -aux => -a -u -x
c.ParserCfg().EnhanceShort = gcli.EnhanceShortAttach // 2: 额外支持 -Ostdout => -O stdout

也可以全局开启:

gcli.SetEnhanceShort(gcli.EnhanceShortMerge)
等级 常量 行为
0 EnhanceShortNone 关闭(默认),完全兼容旧行为
1 EnhanceShortMerge 仅当组合全部为 bool 短选项时才拆分
2 EnhanceShortAttach 额外支持取值紧贴写法 -Ostdout = -O stdout

这里做了一个安全限制:只有当组合里的每个字符都是 bool 短选项时才会拆分。像 -aO(其中 O 需要取值)这种混合写法会原样保留,避免误解析。

7. 健壮性修复

除了新功能,也修了几个历史遗留问题:

  • panic 不再被吞掉gflag.Parser.Parse 过去会忽略 recover 的 panic ,现在会作为 error 返回,方便上层处理。
  • help <命令> 首次调用生效:修复了以前可能提示 unknown input command "help" 的问题。
  • findSimilarCmd 逻辑修正:不再在执行未知命令时往注册表写入幽灵 help 条目。
  • Command.Copy() 修复:不再因为共享指针而清空源命令的 hooks 。

破坏性变更与迁移

有少量清理工作,如果依赖了这些内部实现需要做调整:

之前 现在
import ".../gcli/v3/helper" 已转为内部包,请内联自己的 helper
import ".../gcli/v3/gclicom" 已移除( cliui 迁移后已无用)
全局 --verbose 4 选项 环境变量 GCLI_VERBOSE=debug,或 gcli.SetVerbose(gcli.VerbDebug) / gcli.SetDebugMode()

关于移除 --verbose 的原因:它绑定的是一份应用内副本,底层的日志器并没有读取它,实际上不起作用,反而会让应用的选项列表变乱。控制日志级别请改用环境变量或代码。

另外,同一进程内的多个 App 实例现在会共享全局选项( verbose / help / version / strict / completion )。

升级与示例

go get -u github.com/gookit/gcli/v3@latest

仓库的 _examples/cmd 目录下新增了几个可运行的示例,包括 struct-flag(字段标签+匿名字段)、short-merge(短选项合并)和 ask-demo(交互收集)。

如果遇到问题或有建议,欢迎在 GitHub 提 issue 或 PR 。完整 API 文档参考 GoDoc