Creating waiting/busy indicator for executed process

前端 未结 2 927
一生所求
一生所求 2021-01-19 15:26

i\'ve program which execute child process like

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


        
相关标签:
2条回答
  • 2021-01-19 15:28

    You may use another goroutine to print something (like a dot) periodically, like in every second. When the command completes, signal that goroutine to terminate.

    Something like this:

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

    If you want to start a new line after every 5 dots, this is how it can be done:

    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
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-19 15:51

    Another way is to turn icza's answer around. Since the npm command is a long-running execution, it would probably be better to use a goroutine for it instead of the ticker (or both as a goroutine), but it's a matter of preference.

    Like this:

    func npmInstall(done chan struct{}) {
        cmd := exec.Command("npm", "install")
        log.Printf("Running command and waiting for it to finish...")
    
        err := cmd.Run()
        if err != nil {
            log.Printf("\nCommand finished with error: %v", err)
        }
        close(done)
    }
    
    func main() {
        done := make(chan struct{})
        go npmInstall(done)
    
        ticker := time.NewTicker(3 * time.Second)
        defer ticker.Stop()
        for {
            select {
            case <-ticker.C:
                fmt.Print(".")
            case <-done:
                fmt.Println()
                return
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题