如何将一组动态参数传递给 Go 的命令 exec.Command?

问题描述 投票:0回答:3

我在这里遇到了一个与传递给 Go 的

exec.Command
函数的参数有关的问题,我想知道是否有办法动态传递这些参数?这是 sed 问题的一些示例代码:

package main

import "os/exec"

func main() {
    app := "echo"
    //app := "buah"

    arg0 := "-e"
    arg1 := "Hello world"
    arg2 := "\n\tfrom"
    arg3 := "golang"

    cmd := exec.Command(app, arg0, arg1, arg2, arg3)
    out, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return
    }

    print(string(out))
}

因此,如您所见,每个参数在上面定义为

arg0
arg1
arg2
arg3
。它们与要运行的实际命令一起传递到
Command
函数中,在本例中为
app
var。

如果我有一个参数数组,并且我想要传递的参数数组总是可能具有不确定的计数,该怎么办?这可能吗?

go command exec
3个回答
99
投票

像这样:

args := []string{"what", "ever", "you", "like"}
cmd := exec.Command(app, args...)

查看 golang.org 上的语言和教程。


0
投票

您可以尝试使用flag库,它对我有用。这是一个不同的示例,但它使用接受动态参数的概念。

package main

import (
    "flag"
    "log"
    "os/exec"
    "strings"
)
func main() {
        flag.Parse()    
        arg1, arg2 := strings.Join(flag.Args()[:1], " "), strings.Join(flag.Args()[1:], " ")
        cmd := exec.Command(arg1, arg2)
        err := cmd.Start()
        if err != nil {
            log.Fatal(err)
        }
        log.Printf("Waiting for command to finish...")
        log.Printf("Process id is %v", cmd.Process.Pid)
        err = cmd.Wait()
        log.Printf("Command finished with error, now restarting: %v", err)
}

然后这样跑步

$ go run main.go node ../web-test/index.js
2019/01/26 13:32:29 Waiting for command to finish...
2019/01/26 13:32:29 Process id is 3582

-2
投票

最简单的方法就像Volker的回答一样,使用Variadic(

...
)来辅助。

exec.Command("./myProgram.exe", []string{"foo", "bar"}...)

或者,您可以使用

Stdin
,将您想要传入的所有数据写入缓冲区。

cmd := exec.Command("")
var buf bytes.Buffer
cmd.Stdin = &buf
bur.Write()

您可以考虑使用 JSON 字符串作为输入。然后另一个程序可以读取这个stdin数据来获取你想要传递的内容。

bs, err := json.Marshal(config)
buf.Write(bs)

完整示例

a.go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "log"
    "os/exec"
)

type Config struct {
    User string
    Para []any
}

func main() {
    // cmd := exec.Command("./myProgram.exe", []string{"foo", "bar"}...) // call from exe
    cmd := exec.Command("go", []string{"run", "program/b.go", "foo", "bar"}...)
    // cmd := exec.Command("python", []string{"b.py", "foo", "bar"}...) // call from python
    var buf bytes.Buffer
    cmd.Stdin = &buf

    config := Config{
        "Carson",
        []any{
            "hello world",
            123,
        },
    }
    bs, err := json.Marshal(config)
    if err != nil {
        panic(err)
    }
    buf.Write(bs)

    out, err := cmd.Output() // run and wait for it finished
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("output:\n%s\n", out)
}

b.go
或 (myProgram.exe)

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "os"
)

type Config struct {
    User string
    Para []any
}

func main() {
    _, _ = fmt.Fprintf(os.Stdout, "MyProgram Args:%v\n", os.Args[1:])
    // fmt.Printf("MyProgram Args:%v\n", os.Args[1:]) // same as above, I just want to emphasize the object it writes to.

    bs, err := io.ReadAll(os.Stdin)
    if err != nil {
        log.Fatal(err)
    }

    var config Config
    if err = json.Unmarshal(bs, &config); err != nil {
        log.Fatal(err)
    }
    _, _ = fmt.Fprintf(os.Stdout, "MyProgram Get:\n%+v", config)
}

b.py

import sys
import json

sys.stdout.buffer.write(str.encode(f"MyProgram Args:{sys.argv[1:]}"))
config_raw: bytes = sys.stdin.buffer.read()
config = json.loads(config_raw)
sys.stdout.buffer.write(str.encode("MyProgram Get:" + json.dumps(config)))

a.go 输出

output:
MyProgram Args:[foo bar]
MyProgram Get:
{User:Carson Para:[hello world 123]}
© www.soinside.com 2019 - 2024. All rights reserved.