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

推荐订阅源

博客园 - 【当耐特】
L
Lohrmann on Cybersecurity
Google DeepMind News
Google DeepMind News
Schneier on Security
Schneier on Security
Recent Commits to openclaw:main
Recent Commits to openclaw:main
The Last Watchdog
The Last Watchdog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
N
News and Events Feed by Topic
P
Proofpoint News Feed
H
Heimdal Security Blog
云风的 BLOG
云风的 BLOG
H
Hacker News: Front Page
量子位
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
L
LINUX DO - 最新话题
F
Full Disclosure
小众软件
小众软件
Martin Fowler
Martin Fowler
Security Latest
Security Latest
The Cloudflare Blog
Hacker News: Ask HN
Hacker News: Ask HN
C
Check Point Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
I
InfoQ
AI
AI
Blog — PlanetScale
Blog — PlanetScale
I
Intezer
H
Hackread – Cybersecurity News, Data Breaches, AI and More
M
MIT News - Artificial intelligence
V
Vulnerabilities – Threatpost
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
V2EX
N
News and Events Feed by Topic
C
Cybersecurity and Infrastructure Security Agency CISA
T
Troy Hunt's Blog
大猫的无限游戏
大猫的无限游戏
Hacker News - Newest:
Hacker News - Newest: "LLM"
The Register - Security
The Register - Security
Forbes - Security
Forbes - Security
Recent Announcements
Recent Announcements
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cisco Talos Blog
Cisco Talos Blog
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
S
SegmentFault 最新的问题
S
Securelist
Cloudbric
Cloudbric
T
Tenable Blog
D
Docker

Go 编程语言

[工业边缘网关] EdgeX 更新啦,增加了 MCP,可以被 AI 接管了,可以让 AI 控制物理世界啦 - V2EX [工业边缘网关] 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 V2EX 我开源了一款极简的 P2P 文件传输与 VPN 工具 (Win/Mac/ Linux /Android) - V2EX gookit/gcli v3.5.0 发布 - 简单易用、功能丰富的 Go 命令行应用与工具库 - 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.8:新增支持共享选项、文档生成和参数重排 - V2EX
jxia · 2026-07-01 · via Go 编程语言

GCli v3.8 这一轮补的不是花哨功能,而是写复杂 CLI 时经常会撞到的几个缺口:参数可以写在位置参数后面,结构体绑定支持更多 Go 类型,父命令可以定义会被子命令继承的共享选项,还能直接生成 markdown 和 man 文档。

如果你的 CLI 已经有多级命令、共享配置和文档生成需求,这版会少写不少胶水代码。

先把范围列出来:

  • 参数乱序自动重排:myapp build src/ --name tom 也能解析到 --name
  • 结构体绑定支持 []string[]int[]booltime.Durationmap[string]stringenum
  • 结构体绑定器移除了 unsafe
  • 新增 gflag.Opt[T] / gflag.BindVar[T] 泛型 API 。
  • 新增 Command.SharedOpts(),用于定义会被子命令继承的选项。
  • 新增 docgen 包和内置 gendoc 命令,支持生成 markdown 和 man page 。

还有一个包名调整:events 改名为 gevent,同时在 gcli 包里补了 Evt* 事件名别名。

参数可以写在位置参数后面

GCli 以前和标准库 flag 一样,遇到第一个非 flag 参数后就停止解析选项。下面这种输入里,--name tom 可能不会按预期进入选项解析:

myapp build src/ --name tom

从 v3.6 开始,GCli 会在解析前做一次参数重排。下面两种写法现在结果一致:

myapp build --name tom src/
myapp build src/ --name tom

这个功能默认开启。边界也做了处理:取值型选项会带上自己的值,bool 选项不会误吞后续参数,--opt=val、负数、单独的 --- 之后的内容都会保留原语义。

多级命令里也做了限制:只重排最终执行命令的参数。遇到子命令名后,父命令和子命令的选项不会混在一起。

如果你的程序依赖标准库那种严格顺序,可以关掉:

c.ParserCfg().DisableReorderArgs = true

// 或通过配置函数关闭
gflag.WithReorderArgs(false)

示例在 _examples/cmd/reorder_demo.go

结构体绑定支持更多 Go 类型

结构体绑定是 GCli 里很常用的一块。v3.7 之前,如果要绑定列表、map 或时长,经常要绕到 gflag.StringsKVString 这类辅助类型上。现在可以直接使用常见 Go 类型:

type deployOpts struct {
    Names []string          `flag:"name=names;shorts=n;desc=name list"`
    Ports []int             `flag:"name=ports;shorts=p;desc=port list"`
    TTL   time.Duration     `flag:"name=ttl;desc=time to live, eg: 1h30m"`
    Meta  map[string]string `flag:"name=meta;shorts=m;desc=key=value metadata"`
    Lang  string            `flag:"name=lang;shorts=l;desc=language;enum=go,php,java"`
}

c.MustFromStruct(&deployOpts{})

对应命令可以这样写:

myapp deploy -n a -n b -p 80 -p 443 --ttl 1h30m -m k1=v1 -m k2=v2 -l go

实际变化有几条:

  • []string[]int[]bool 会绑定成可重复选项。
  • time.Duration 使用 Go 原生时长格式,例如 1h30m
  • map[string]string 支持重复传入 key=value
  • enum:"go,php,java" 会用于补全候选值,也会在解析时做成员校验。

实现上,结构体绑定器不再使用 unsafe,改为通过 reflect.Value.Addr().Interface() 获取字段指针。用户侧基本无感,但维护成本低一些。

另外,匿名嵌套结构体现在在 namedsimplefield 三种标签规则下都会展开。v3.8 还修复了内嵌未导出类型此前不会展开的问题。

泛型 API 少记几个方法名

传统 API 仍然保留:BoolVarIntVarStrVarFloat64Var 这些都能继续用。

v3.7 新增了一个泛型入口,会根据指针类型选择对应的绑定器:

var (
    name string
    age  int
    tags []string
    ttl  time.Duration
)

gflag.Opt(&c.Flags, &name, "name", "n", "tom", "the user name")
gflag.Opt(&c.Flags, &age,  "age",  "a", 18,    "the user age")
gflag.Opt(&c.Flags, &tags, "tag",  "t", nil,   "the tags, repeatable")
gflag.Opt(&c.Flags, &ttl,  "ttl",  "",  time.Duration(0), "time to live")

如果需要完整控制选项元数据,可以用 gflag.BindVar[T]

var langs []string
gflag.BindVar(&c.Flags, &langs, gflag.NewOpt("langs", "language list", nil))

这不是替代所有旧 API 的大改造,只是给新代码一个更顺手的入口。

SharedOpts 补上了父子命令之间的中间层

v3.8 里最值得单独拿出来说的是 Command.SharedOpts()

GCli 以前有应用级全局选项和命令级局部选项,但缺少一个“父命令定义,子命令继承”的中间层。SharedOpts() 补的就是这层语义,接近 cobra 的 PersistentFlags

var gitDir string

top := &gcli.Command{Name: "git", Desc: "git-like demo"}
top.SharedOpts().StrOpt(&gitDir, "git-dir", "", ".git", "the git data dir")

top.Add(&gcli.Command{
    Name: "status",
    Func: func(c *gcli.Command, _ []string) error {
        gcli.Printf("git dir: %s\n", gitDir)
        return nil
    },
})

下面几种写法都会让 gitDir 得到 /x

myapp git --git-dir /x status
myapp git status --git-dir /x
myapp git status arg --git-dir /x

几个规则需要注意:

  • 子命令上的同名局部选项优先级更高。
  • Required 的共享选项会在最终执行的叶子命令上校验。
  • 子命令帮助中,祖先命令继承来的选项会放到 Inherited Options 分组。

底层新增了 Parser.InheritOptsFrom(src, category...),继承选项会按底层 flag.Value 重新注册,所以父子命令写的是同一个绑定变量。

docgen 可以直接生成 markdown 和 man page

v3.8 新增了 docgen 包,可以把单个命令或整个应用导出成 markdown 或 man page:

import "github.com/gookit/gcli/v3/docgen"

docgen.MarkdownTree(app, "./docs")
docgen.ManTree(app, "./man")

md  := docgen.CmdMarkdown(cmd)
man := docgen.CmdMan(cmd)

也可以从命令行触发。把内置命令注册进去:

import "github.com/gookit/gcli/v3/builtin"

app.Add(builtin.GenDoc())

然后执行:

./cliapp gendoc -f md  -o ./docs
./cliapp gendoc -f man -o ./man

生成器会顺手处理命令行文档里容易漏掉的小细节:清理 Examples 里的颜色标签,展开 {$fullCmd} 这类内置变量,保留多行示例,并在应用概览里写入版本信息。选项表也会通过 gflag.CliOpt.TypeName() 带上类型。

迁移注意点

从 v3.5 升上来,有两处可能需要改代码。

事件包改名:

之前 现在
import "github.com/gookit/gcli/v3/events" import "github.com/gookit/gcli/v3/gevent"
events.OnCmdRunBefore gevent.OnCmdRunBeforegcli.EvtCmdRunBefore

应用级解析状态移动:

之前 现在
GlobalOpts.ShowHelp / ShowVersion / inCompletion / genCompletion 新的应用级 AppOptions,通过 app.AppOpts() 访问

App.Opts() 仍然返回进程级的 *GlobalOpts,所以 app.Opts().Verboseapp.Opts() == gcli.GOpts() 这类用法不变。移动的是那些描述单个 App 解析状态的字段,避免同一进程内多个 App 实例互相影响。

参数自动重排也是行为变化,只是它通常会让输入更宽容。如果你确实依赖旧行为,可以设置 Config.DisableReorderArgs = true

升级

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

升级后建议先看三个示例:reorder-argsstruct-typesstruct-flag。它们覆盖了这次最容易影响实际代码的几块能力。

问题和建议可以继续在 GitHub Issues 里提。