23427


Go の初心者です。

Golang で、正しく動いている次のコードがあります。

[code]

    package main
    
    import "os/exec"
    import fmt "fmt"
    
    func main() {
    
         c, _ := exec.Command("git", "log", "--first-parent", "--merges").Output()
         s := string(c[:])
         fmt.Printf(s)
    }
    
[/code]

* * *

これの、コマンド実行部分を関数に切り出そうとして、次のように変更を行いました。

[code]

    package main
    
    import "os/exec"
    import fmt "fmt"
    
    func executeCommand(command ...string) string {
         c, _ := exec.Command(command...).Output()
         return string(c[:])
    }
    
    func main() {
    
         s := executeCommand("git", "log", "--first-parent", "--merges")
         fmt.Printf(s)
    }
    
[/code]

すると、次のエラーが発生します。

[code]

    # command-line-arguments
    ./calc.go:7:27: error: argument 1 has incompatible type
          c, _ := exec.Command(command...).Output()
                               ^
    ./calc.go:7: confused by earlier errors, bailing out
    
[/code]

`command...` で、受け取った配列を展開して、 `exec.Command()`
に引き渡せるものだと思っていたのですが、上記の通りそうはなっていないです。

* * *

質問:

  * 私は、何を間違えているのでしょうか。


CC BY-SA 3.0
2016-03-24T14:54:57.740
23426
2016-03-24T16:27:39.610
754
question
go
golang で受け取った可変長引数を他の可変長引数に渡したい


エラーメッセージにあるとおりです。 `exec.Command` は第1引数は `string` なので、スライスではなく `string`
を渡す必要があります。

<https://golang.org/pkg/os/exec/#Command>

[code]

    package main
    
    
    import (
        "fmt"
        "os/exec"
    )
    
    func executeCommand(command ...string) string {
        c, _ := exec.Command(command[0], command[1:]...).Output()
        return string(c[:])
    }
    
    func main() {
        s := executeCommand("git", "log", "--first-parent", "--merges")
        fmt.Println(s)
    }
    
[/code]


CC BY-SA 3.0
2016-03-24T15:07:31.253
23427
2016-03-24T15:07:31.253
216
23426
answer


本題からは外れるのですが、`exec.Command()` の signature が

[code]

    func Command(name string, arg ...string)
    
[/code]

となっていますので、`executeCommand()` もこれに合わせる方が良いかと思います。

可変長引数だけにすると引数がない場合でも compile error にならずに `executeCommand()` が実行されてしまい、その結果
runtime error が発生してしまいます。

[code]

    s := executeCommand()
    
    panic: runtime error: slice bounds out of range
    
[/code]

どうしても可変長引数だけにしたい場合は可変長引数(`command`)の length check などをしておくべきかと思います。


CC BY-SA 3.0
2016-03-24T16:27:39.610
23429
2016-03-24T16:27:39.610
23426
answer