kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 -33- <time.Sleep,Run>

こんにちは、kurumi-bioです。
第4回目のexecパッケージ(標準ライブラリー)の学習です。

環境

  • Windows
    OSバージョン:Windows11 Home 22H2
    Go言語のバージョン:go version go1.20.3 windows/amd64
  • Linux
    OSバージョン:openSUSE Leap 15.4
    Go言語のバージョン:go version go1.20.1 linux/amd64

[time package] Sleep関数

func Sleep(d Duration)

関数の説明スリープは、現在のゴルーチンを少なくともd期間一時停止します。負またはゼロの期間は、Sleep をすぐに復帰させます。

◆テストコード

package main

import (
    "fmt"
    "os"
    "strconv"
    "time"
)

func main() {
    if len(os.Args) != 2 {
        fmt.Fprintf(os.Stderr, "usage: sleep ms")
        os.Exit(1)
    }
    i, _ := strconv.Atoi(os.Args[1])
    t := time.Duration(i)
    time.Sleep(t * time.Second)
    fmt.Fprintf(os.Stderr, "Success")
}

コードの説明 Cmd.Run()関数を試すためのテストコードです。
timeパッケージのSleep関数を使って、起動時の引数で指定された期間(秒)一時停止します。
正常に完了した場合、一時停止後に標準エラー出力に"Success"と出力します。 起動時の引数が足りない場合は、標準エラー出力にusageを出力します。

◆実行結果(Windows)

実行結果の説明 実行時の引数を指定した場合は、指定した期間経過後に標準エラー出力Successと出力されます。
実行時の引数を指定しなかった場合は、標準エラー出力usage: Sleep 秒と出力されます。

Run関数

func (c *Cmd) Run() error

関数の説明Run は、指定されたコマンドを開始し、完了するまで待機します。
コマンドが実行され、stdin、stdout、および stderr のコピーに問題がなく、ゼロの終了ステータスで終了する場合、返されるエラーは nil です。
コマンドが開始しても正常に完了しない場合、エラーのタイプは *ExitError です。他の状況では、他のエラー タイプが返される場合があります。
呼び出し元のゴルーチンが runtime.LockOSThread でオペレーティング システム スレッドをロックし、継承可能な OS レベルのスレッド状態 (Linux または Plan 9名前空間など) を変更した場合、新しいプロセスは呼び出し元のスレッド状態を継承します。

◆テストコード

package main

import (
    "fmt"
    "os"
    "os/exec"
    "time"
)

func main() {
    c := exec.Command("./Sleep.exe", "3")
    c.Stderr = os.Stderr
    n := time.Now()
    fmt.Println("Start")
    e := c.Run()
    fmt.Printf("End:[%1.1f 秒経過]\n", time.Since(n).Seconds())
    if e != nil {
        fmt.Fprint(os.Stderr, "error=[%v]\n", e)
        fmt.Println(e)
    }
}

コードの説明 Sleep.exeコマンドを実行して、Cmd.Run()関数の実行時間(秒)を出力するプログラムです。

◆実行結果(Windows)

実行結果の説明 経過秒数がSleep.exeコマンドの起動引数と同じになっていることから、 Cmd.Run()関数は、コマンドが完了するまで待機していることがわかります。
また、標準エラー出力への出力のあるなしは関係なく、Sleep.exeコマンドの終了ステータスが0なので、戻り値のエラーはnilになっています。

◆テストコード

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    c := exec.Command("./sleep.exe")
    c.Stderr = os.Stderr
    e := c.Run()

    if e != nil {
        var ee *exec.ExitError
        var flag bool
        ee, flag = e.(*exec.ExitError)
        if flag {
            fmt.Println("")
            fmt.Printf("ExitCode=[%d]\n", ee.ProcessState.ExitCode())
            fmt.Printf("Pid=[%d]\n", ee.ProcessState.Pid())
            fmt.Printf("Stderr=[%s]\n", string(ee.Stderr))
        }
        fmt.Fprintf(os.Stderr, "Error=[%v]\n", e)
    }
}

コードの説明 Sleep.exeコマンドを引数なしで実行します。
戻り値のエラーに値がある場合は、エラーが*exec.ExitError型の場合はExitCodeなどを出力します。

◆実行結果(Windows)

実行結果の説明 Sleep.exeコマンドを引数なしで実行したため、標準エラー出力にusageが出力されました。
さらに終了ステータスが1なので、戻り値のエラーに*ExitError型の値が入りました。

◆テストコード

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    c := exec.Command("./sleep2.exe")
    c.Stderr = os.Stderr
    e := c.Run()

    if e != nil {
        var ee *exec.ExitError
        var flag bool
        ee, flag = e.(*exec.ExitError)
        if flag {
            fmt.Println("")
            fmt.Printf("ExitCode=[%d]\n", ee.ProcessState.ExitCode())
            fmt.Printf("Pid=[%d]\n", ee.ProcessState.Pid())
            fmt.Printf("Stderr=[%s]\n", string(ee.Stderr))
        }
        fmt.Fprintf(os.Stderr, "Error=[%v]\n", e)
    }
}

コードの説明 存在しないコマンド(Sleep2.exe)コマンドを実行します。

◆実行結果(Windows)

実行結果の説明 file does not existが戻り値のエラーに返されました。 コマンドが実行されなかったため終了ステータスが取得できず*ExitError以外の型になりました。

最後までご覧いただきありがとうございます