为执行的进程创建等待/忙碌指示器

4 command-line command-line-interface go

我有执行子进程的程序,例如

cmd := exec.Command("npm", "install")
log.Printf("Running command and waiting for it to finish...")
err := cmd.Run()
log.Printf("Command finished with error: %v", err)
Run Code Online (Sandbox Code Playgroud)

当此命令运行时,它会下载并安装 npm 包,这需要 10 到 40 秒的时间,用户在看到标准输出(10-40 秒取决于网络)之前不知道会发生什么,我可以做一些事情使用 which 将某些内容打印到 cli 以更清楚地表明某些事情发生了,一些繁忙的指示器(任何类型),直到将 stdout 打印到 cli ?

icz*_*cza 5

你可以使用另一个 goroutine 定期打印一些东西(比如一个点),比如每秒。当命令完成时,通知 goroutine 终止。

像这样的东西:

func indicator(shutdownCh <-chan struct{}) {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()
    for {
        select {
        case <-ticker.C:
            fmt.Print(".")
        case <-shutdownCh:
            return
        }
    }
}

func main() {
    cmd := exec.Command("npm", "install")
    log.Printf("Running command and waiting for it to finish...")

    // Start indicator:
    shutdownCh := make(chan struct{})
    go indicator(shutdownCh)

    err := cmd.Run()

    close(shutdownCh) // Signal indicator() to terminate

    fmt.Println()
    log.Printf("Command finished with error: %v", err)
}
Run Code Online (Sandbox Code Playgroud)

如果您想在每 5 个点后开始一个新行,可以这样做:

func indicator(shutdownCh <-chan struct{}) {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()
    for i := 0; ; {
        select {
        case <-ticker.C:
            fmt.Print(".")
            if i++; i%5 == 0 {
                fmt.Println()
            }
        case <-shutdownCh:
            return
        }
    }
}
Run Code Online (Sandbox Code Playgroud)