urfave/cli/v2中父Command如何初始化资源传递给Subcommands
实现方案
完全可以,不需要创建多个cli.App这么繁琐,用urfave/cli/v2原生的命令级Before钩子结合context.Context传值就能优雅实现。
核心逻辑
- 父命令
db的Before钩子会在所有下属子命令的Action执行前触发,此时父命令的--connect参数已经完成解析,可以直接用来初始化DB资源 - 初始化完成的DB实例通过
context.WithValue注入到上下文,子命令的Action直接从传入的*cli.Context中取出即可复用
代码示例
package main import ( "context" "log" "os" "github.com/urfave/cli/v2" ) // 自定义非导出的上下文key类型,避免和其他包的key冲突 type ctxKey int const dbCtxKey ctxKey = iota func main() { app := &cli.App{ Name: "mycmd", Commands: []*cli.Command{ { Name: "db", Flags: []cli.Flag{ &cli.StringFlag{ Name: "connect", Required: true, Usage: "数据库连接串", }, }, // 父命令前置钩子,所有子命令执行前都会先运行这段逻辑 Before: func(c *cli.Context) error { connStr := c.String("connect") // 替换为实际的DB初始化逻辑 db, err := initDB(connStr) if err != nil { return err } // 将初始化好的DB注入上下文 c.Context = context.WithValue(c.Context, dbCtxKey, db) return nil }, // 子命令如果需要释放资源,可以在这里加After钩子统一处理 After: func(c *cli.Context) error { db := c.Context.Value(dbCtxKey).(*DB) // 替换为实际的DB关闭逻辑 log.Println("关闭DB连接:", db.connStr) return nil }, Subcommands: []*cli.Command{ { Name: "create", Action: func(c *cli.Context) error { // 直接从上下文取复用的DB实例 db := c.Context.Value(dbCtxKey).(*DB) // 这里的*DB替换为实际的DB实例类型 // 替换为实际的create业务逻辑 log.Println("执行create操作,使用连接:", db.connStr) return nil }, }, { Name: "update", Action: func(c *cli.Context) error { db := c.Context.Value(dbCtxKey).(*DB) // 替换为实际的update业务逻辑 log.Println("执行update操作,使用连接:", db.connStr) return nil }, }, }, }, }, } if err := app.Run(os.Args); err != nil { log.Fatal(err) } } // 示例DB结构体和初始化方法,替换为实际实现 type DB struct { connStr string } func initDB(connStr string) (*DB, error) { log.Println("初始化DB连接:", connStr) return &DB{connStr: connStr}, nil }
运行验证
执行命令mycmd db --connect "user:pass@tcp(127.0.0.1:3306)/test" create,输出顺序如下:
2024/xx/xx xx:xx:xx 初始化DB连接: user:pass@tcp(127.0.0.1:3306)/test 2024/xx/xx xx:xx:xx 执行create操作,使用连接: user:pass@tcp(127.0.0.1:3306)/test 2024/xx/xx xx:xx:xx 关闭DB连接: user:pass@tcp(127.0.0.1:3306)/test
DB只会初始化一次,所有子命令都可以复用同一个实例,资源释放也只需要统一写一次。
内容的提问来源于stack exchange,提问作者user1957145
相关产品推荐
相关产品推荐

