Go by Example မြန်မာဘာသာ: Spawning Processes

တစ်ခါတလေမှာ ကျွန်တော်တို့ရဲ့ Go ပရိုဂရမ်တွေဟာ Go မဟုတ်တဲ့ တခြား လုပ်ငန်းစဉ် (processes) တွေကို လုပ်ဆောင်ဖို့ လိုအပ်ပါတယ်။

package main
import (
    "fmt"
    "io"
    "os/exec"
)
func main() {

ကျွန်တော်တို့က argument တွေ၊ input တွေ မလိုအပ်ပဲ stdout ပေါ်မှာ တစ်ခုခုကို ရိုက်ထုတ်ပြတဲ့ ရိုးရှင်းတဲ့ command တစ်ခုနဲ့ စမယ်။ exec.Command helper က ဒီ ပြင်ပ လုပ်ငန်းစဉ်ကို ကိုယ်စားပြုဖို့ object တစ်ခုကို ဖန်တီးပေးပါတယ်။

    dateCmd := exec.Command("date")

Output method က command ကို run ပြီး အဆုံးသတ်တဲ့အထိ စောင့်ပြီး သူ့ရဲ့ standard output ကို စုဆောင်းပါတယ်။ အမှားမရှိဘူးဆိုရင် dateOut မှာ ရက်စွဲအချက်အလက်ပါတဲ့ bytes တွေ ပါဝင်မှာဖြစ်ပါတယ်။

    dateOut, err := dateCmd.Output()
    if err != nil {
        panic(err)
    }
    fmt.Println("> date")
    fmt.Println(string(dateOut))

Output နဲ့ Command ရဲ့ တခြား method တွေဟာ command ကို run ဖို့ ပြဿနာရှိခဲ့ရင် (ဥပမာ - မှားယွင်းတဲ့လမ်းကြောင်း) *exec.Error ကို return ပြန်ပြီး၊ command က run ပေမယ့် non-zero return code နဲ့ ထွက်သွားခဲ့ရင် *exec.ExitError ကို return ပြန်ပါတယ်။

    _, 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 ပေါ်ကို data တွေ pipe လုပ်ပြီး သူ့ရဲ့ stdout ကနေ ရလဒ်တွေကို စုဆောင်းတဲ့ နည်းနည်းပိုရှုပ်ထွေးတဲ့ ကိစ္စကို ကြည့်ကြမယ်။

    grepCmd := exec.Command("grep", "hello")

ဒီမှာတော့ input/output pipes တွေကို အတိအကျ ယူပြီး၊ လုပ်ငန်းစဉ်ကို စတင်၊ အထဲကို input တချို့ ရေးထည့်၊ ထွက်လာတဲ့ output ကို ဖတ်ယူပြီး နောက်ဆုံးမှာ လုပ်ငန်းစဉ် ပြီးဆုံးတဲ့အထိ စောင့်ပါတယ်။

    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 pattern ကို အားလုံးအတွက် သုံးနိုင်ပါတယ်။ ကျွန်တော်တို့က StdoutPipe ရလဒ်တွေကိုပဲ စုဆောင်းထားပေမယ့် သင်က အတူတူပဲ StderrPipe ကိုလည်း စုဆောင်းနိုင်ပါတယ်။

    fmt.Println("> grep hello")
    fmt.Println(string(grepBytes))

မှတ်သားရန် - command တွေကို spawn လုပ်တဲ့အခါ command-line string တစ်ခုတည်းကို ပေးနိုင်တာမဟုတ်ဘဲ၊ အတိအကျ သတ်မှတ်ထားတဲ့ command နဲ့ argument array ကို ပေးဖို့ လိုအပ်ပါတယ်။ သင်က string တစ်ခုနဲ့ အပြည့်အစုံ command တစ်ခုကို spawn လုပ်ချင်ရင် bash ရဲ့ -c option ကို သုံးနိုင်ပါတယ်။

    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))
}

ဖန်တီးထားတဲ့ ပရိုဂရမ်တွေက ထွက်လာတဲ့ output ဟာ ကျွန်တော်တို့ command-line ကနေ တိုက်ရိုက် run သလိုပဲ ဖြစ်ပါတယ်။

$ go run spawning-processes.go 
> date
Thu 05 May 2022 10:10:12 PM PDT

date မှာ -x flag မရှိတဲ့အတွက် အမှားပြ message နဲ့အတူ non-zero return code နဲ့ ထွက်သွားပါလိမ့်မယ်။

command exited with rc = 1
> grep hello
hello grep
> ls -a -l -h
drwxr-xr-x  4 mark 136B Oct 3 16:29 .
drwxr-xr-x 91 mark 3.0K Oct 3 12:50 ..
-rw-r--r--  1 mark 1.3K Oct 3 16:28 spawning-processes.go

နောက်ဥပမာ: Exec'ing Processes.