如何将数据库连接传递给所有 cobra 命令?

问题描述

所以我创建了一个眼镜蛇命令

func init() {
    rootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
    Use:   "version",Short: "Show App version",Long:  "Show App version.",Run: func(cmd *cobra.Command,args []string) {
        dir,_ := os.Getwd()
        db,err := gorm.Open(sqlite.Open(fmt.Sprintf("%s/db/db.sqlite",dir)),&gorm.Config{})
        if err != nil {
            panic("Failed to connect database")
        }
    
       ....
    },}

可以看到里面的数据库连接代码。现在我必须在所有命令中添加相同的数据库连接代码。有什么办法可以避免这种情况吗?

解决方法

您可以创建一个方法来初始化 db 并在 RUN arg 中使用该方法。尝试以下操作:

for i in range(0,2):
     for j in range(0,2): 
                 stuff

或者,如果 var versionCmd = &cobra.Command{ ..... Run: func(cmd *cobra.Command,args []string) { db := initDB() .... },} func initDB() *gorm.DB { dir,_ := os.Getwd() db,err := gorm.Open(sqlite.Open(fmt.Sprintf("%s/db/db.sqlite",dir)),&gorm.Config{}) if err != nil { panic("failed to connect database") } return db } 函数也适用于其他命令,您可以提取该函数本身。

Run
,

我建议采用以下方法:

type RunEFunc func(cmd *cobra.Command,args []string) error

func NewCmd(db *gorm.DB) *cobra.Command {
    cmd := &cobra.Command{
            ...
        RunE: runCmd(db),}

    return cmd
}

func runCmd(db *gorm.DB) RunEFunc {
    return func(cmd *cobra.Command,args []string) error {
        // Use db here
}

它也很容易测试:

func TestCmd(t *testing.T) {
    db := // Open db
    cmd := NewCmd(db)
    cmd.SetArgs([]string{"any here"})
    // You can also modify flags
    if err := cmd.Execute(); err != nil {
        t.Fatal(err)
    }
}

有时为了测试目的传递数据库对象之外的其他参数是很方便的。 Here 是一个实现及其 test