问题描述
https://github.com/spf13/cobra#prerun-and-postrun-hooks
如何将命令状态传递给 PostRun 调用? 我需要在执行后将命令状态发布到服务器
解决方法
更简洁的方法是利用 cobra 命令中提供的注释
package main
import (
"fmt"
"github.com/spf13/cobra"
)
func main() {
var rootCmd = &cobra.Command{
Use: "root [sub]",Short: "My root command",Run: func(cmd *cobra.Command,args []string) {
// Do your processing here
// Set the command annotations
cmd.Annotations = make(map[string]string)
cmd.Annotations["status"] = "status_goes_here"
cmd.Annotations["error"] = "error_goes_here"
},PostRun: func(cmd *cobra.Command,args []string) {
// Retrieve the annotations
fmt.Println(cmd.Annotations["status"])
fmt.Println(cmd.Annotations["error"])
},}
rootCmd.SetArgs([]string{"sub","arg1","arg2"})
rootCmd.Execute()
}
真的很喜欢@Bracken 在这里采取的方法,尽管有一些调整可以使它起作用
package main
import (
"fmt"
"errors"
"github.com/spf13/cobra"
)
type wrapper struct {
err error
}
// RunE fails to proceed further in case of error resulting in not executing PostRun actions
func (w *wrapper) Run(f func(cmd *cobra.Command,args []string) error) func(cmd *cobra.Command,args []string) {
return func(cmd *cobra.Command,args []string) {
err := f(cmd,args)
w.err = err
}
}
func (w *wrapper) PostRun(f func(cmd *cobra.Command,args []string,cmdErr error)) func(cmd *cobra.Command,args []string) {
f(cmd,args,w.err)
}
}
func main() {
cmdWrap := wrapper{}
var rootCmd = &cobra.Command{
Use: "root [sub]",Run: cmdWrap.Run(func(cmd *cobra.Command,args []string) error {
return errors.New("i'm not in the book,you know")
}),PostRun: cmdWrap.PostRun(func(cmd *cobra.Command,cmdErr error) {
fmt.Printf("error was %v\n",cmdErr)
}),"arg2"})
rootCmd.Execute()
}
----- 旧答案 -----
如果我理解正确,有一些状态需要从 cmd.Execute 传递到 PostRun。
您可以使用 ExecuteContext(ctx context.Context)
方法代替 Execute()
并设置需要在上下文中设置的任何键值。
ctx := context.WithValue(context.Background(),"status","statusValue")
rootCmd.ExecuteContext(ctx)
可以使用 cmd.Context()
PostRun: func(cmd *cobra.Command,args []string) {
ctx := cmd.Context()
status := ctx.Value("status")
}
,
我会使用高阶函数来包装您的 Run
(或 RunE
)函数和 PostRun
函数以捕获错误或恐慌,然后将它们传递到您的 PostRun
中:
package main
import (
"fmt"
"github.com/spf13/cobra"
)
type wrapper struct {
err error
}
func (w *wrapper) RunE(f func(cmd *cobra.Command,args []string) error {
return func(cmd *cobra.Command,args []string) (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic: %v",r)
w.err = err
}
}()
err = f(cmd,args)
w.err = err
return
}
}
func (w *wrapper) PostRun(f func(cmd *cobra.Command,w.err)
}
}
func main() {
cmdWrap := wrapper{}
var cmdFail = &cobra.Command{
Use: "fail",Short: "Doesn't work",RunE: cmdWrap.RunE(func(cmd *cobra.Command,args []string) error {
panic("i'm not in the book,}
var rootCmd = &cobra.Command{}
rootCmd.AddCommand(cmdFail)
rootCmd.Execute()
}