小编典典

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

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)

运行此命令时,它会下载并安装npm软件包,这需要花费10到40秒的时间,并且用户直到看到标准输出(10-40秒取决于网络)才知道发生了什么,我可以做一些事情使用哪个可以在cli上打印一些东西,以便更清楚地说明发生了什么事情,一些忙碌的指示器(任何类型),直到将stdout打印到cli上?


阅读 262

收藏
2020-07-02

共1个答案

小编典典

您可以使用另一个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)
}

如果要在每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
        }
    }
}
2020-07-02