Share properties from separate commands/process

折月煮酒 提交于 2019-12-05 12:43:34

Share information between commands

Like was said in comments, if you need to share data across commands, you'll need to persist it. The structure you use is no relevant, but for simplicity and because of JSON is the current most extended language for data exchange we'll use it.


Where should I create it (path)?

My recomendation is to use the home of the user. Many applications save its configuration here. This will allow a solution multi-environment easily. Say that your configuration file will be named myApp.

func configPath() string {
    cfgFile := ".myApp"
    usr, _ := user.Current()
    return path.Join(usr.HomeDir, cfgFile)
}


When to clean it ?

That obviously will depend on your requirements. But, if you always need to run pre and run in that order, I bet that you can clean it inmediately after run execution, when it won't be longer needed.


How to store it ?

That's easy. If what you need to save is your config struct you can do this:

func saveConfig(c config) {
    jsonC, _ := json.Marshal(c)
    ioutil.WriteFile(configPath(), jsonC, os.ModeAppend)
}


And to read it ?

func readConfig() config {
    data, _ := ioutil.ReadFile(configPath())
    var cfg config
    json.Unmarshal(data, &cfg)
    return cfg
}


Flow

// pre command
// persist to file the data you need
saveConfig(config{ 
    id:   "id",
    path: "path",
    wd:   "wd",
}) 

// run command
// retrieve the previously stored information
cfg := readConfig()

// from now you can use the data generated by `pre`

DISCLAIMER: I've removed all error handling for short.

If you are trying to persist state across execution of different commands of a command line tool, the you have 2 choices.

  1. Write the state to some kind of file (consider the env a file in this case).
  2. Output values from the first command in a way that can be used as the input to another command.

On 1.

I think it's good practice for any arguments etc. to only survive for the lifetime of the running of the CLI tool. The equivalent of the smallest scoped variables possible in programming. This works well when you need to persist the state indefinitely, but if your state is no longer used after the initProcess command has finished then this is probably not the right option.

On 2.

There is some precedence for this. The unix philosophy (wikipedia) suggests to:

Expect the output of every program to become the input to another

So you could pick some output (to stdout) format for the first prepare command that could be used as the input for the second initProcess command. And then use | pipe to run the output of one into the other.

Example:

func Run(cmd *cobra.Command, args []string) {
    //This creating the temp folder and validate some configuration file    
    tmpFolderPath,parsedFile := exe.PreProcess()
    fmt.Println(tmpFolderPath)
    fmt.Println(parsedFile)
}

func InitProcess(cmd *cobra.Command, args []string) {

    tmpFolder, parsedFile := args[0], args[1]

}

Then to run the program, and pipe the commands together:

./program pre | xargs ./program run
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!