Go 程式有時需要執行其他非 Go 的處理程序。
|
|
|

package main
|
|
import (
"fmt"
"io"
"os/exec"
)
|
|
func main() {
|
我們從不帶任何參數或輸入,只會將資料列印到 stdout 的簡單指令開始。exec.Command 輔助程式會建立一個用於表示這個外部處理程序的物件。
|
dateCmd := exec.Command("date")
|
Output 方法會執行指令,並在執行完畢後收集其標準輸出。如果沒有錯誤,dateOut 將會儲存日期資訊的位元組。
|
dateOut, err := dateCmd.Output()
if err != nil {
panic(err)
}
fmt.Println("> date")
fmt.Println(string(dateOut))
|
如果執行指令時出現問題 (例如,路徑錯誤),Output 和 Command 的其他方法會傳回 *exec.Error ,而如果指令執行完畢但傳回非零回傳碼,則會傳回 *exec.ExitError 。
|
_, err = exec.Command("date", "-x").Output()
if err != nil {
switch e := err.(type) {
case *exec.Error:
fmt.Println("failed executing:", err)
case *exec.ExitError:
fmt.Println("command exit rc =", e.ExitCode())
default:
panic(err)
}
}
|
接下來,我們會檢視一個稍微複雜一點的案例,其中我們將資料導向外部處理程序的 stdin ,並收集結果自其 stdout 。
|
grepCmd := exec.Command("grep", "hello")
|
在此,我們明確地取得輸入/輸出導管,啟動處理程序,寫入一些輸入資料,讀取產生的輸出資料,最後等待處理程序結束。
|
grepIn, _ := grepCmd.StdinPipe()
grepOut, _ := grepCmd.StdoutPipe()
grepCmd.Start()
grepIn.Write([]byte("hello grep\ngoodbye grep"))
grepIn.Close()
grepBytes, _ := io.ReadAll(grepOut)
grepCmd.Wait()
|
我們省略前述範例中的錯誤檢查,但可以對所有這些檢查使用常見的 if err != nil 模式。我們也只收集 StdoutPipe 結果,但可以完全相同的方式收集 StderrPipe 。
|
fmt.Println("> grep hello")
fmt.Println(string(grepBytes))
|
請注意,當執行指令時,我們需要提供明確界定的指令和參數陣列,而不是只能傳入一個指令列字串。如果您想使用字串執行完整的指令,可以使用 bash 的 -c 選項。
|
lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
lsOut, err := lsCmd.Output()
if err != nil {
panic(err)
}
fmt.Println("> ls -a -l -h")
fmt.Println(string(lsOut))
}
|