英文:
Pass resource from Command To Subcommands in urfave/cli/v2
问题
是否可能,并且如果可能的话,如何让一个Command
初始化一个资源并将其传递给其Subcommands
。想象一个以以下方式接收参数的应用程序:
$ mycmd db --connect <...> create <...>
$ mycmd db --connect <...> update <...>
这可能不是一个很好的例子,但它说明了这个概念。这里的db
是所有子命令都依赖的某个资源。我希望有一个单独的函数负责初始化db
资源,然后将初始化后的资源传递给子命令。我无法弄清楚如何在urfave/cli/v2
中实现这一点。
你可以通过创建两个独立的cli.App
来实现,一个用于解析参数中的db
部分,只是为了创建一个带有context.WithValue
的context.Context
,然后使用该上下文创建第二个cli.App
,用于解析剩余的参数。我相信有更好的方法来实现这一点。
非常感谢任何帮助!
英文:
Is is possible, and if so how, to let a Command
initialize a resource and pass it down to its Subcommands
. Image an application that takes its arguments like
$ mycmd db --connect <...> create <...>
$ mycmd db --connect <...> update <...>
This may not be a great example but it illustrates the concept. Here db
is some resource that all the subcommands depend on. I would like a single function to be responsible for the initialization of the db
resource and then pass the initialized resource down to the subcommands. I can't figure out how to do this with urfave/cli/v2
.
You could do it by creating two separate cli.App
s, one that parses the db
part of the arguments just to create a context.Context
with context.WithValue
and then use that context to create the second cli.App
which would parse the remainder of the arguments. I'm sure there's a better way to do it.
I'm grateful for any help!
答案1
得分: 1
你可以通过上下文值来实现这一点。你可以在父级Command
的Before
回调中设置该值。下面的代码是从subcommands示例中复制并修改的:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Commands: []*cli.Command{
{
Name: "db",
Before: func(c *cli.Context) error {
db := "example"
c.Context = context.WithValue(c.Context, "db", db)
return nil
},
Subcommands: []*cli.Command{
{
Name: "connect",
Action: func(c *cli.Context) error {
db := c.Context.Value("db").(string) // 记得断言为原始类型
fmt.Println("sub command:", db)
return nil
},
},
},
},
},
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
这个示例使用了一个string
,这样你就可以复制粘贴并运行它。你可以用你的DB对象替换字符串。
如何测试:
$ go build -o example
$ ./example db connect
sub command: example
英文:
You can achieve this with context values. You set the value in the Before
callback of the parent Command
. Below code is copied and modified from the subcommands example:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Commands: []*cli.Command{
{
Name: "db",
Before: func(c *cli.Context) error {
db := "example"
c.Context = context.WithValue(c.Context, "db", db)
return nil
},
Subcommands: []*cli.Command{
{
Name: "connect",
Action: func(c *cli.Context) error {
db := c.Context.Value("db").(string) // remember to assert to original type
fmt.Println("sub command:", db)
return nil
},
},
},
},
},
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
This main uses a string
so that you can copy paste and run it. You can replace string with your DB object.
How to test:
$ go build -o example
$ ./example db connect
sub command: example
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论