如何在眼镜蛇 cli 中将命令状态传递给 Postrun

问题描述

Cobra CLI 支持在执行命令后调用 PostRun。

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 中检索相同的值
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()
}