i\'ve program which execute child process like
cmd := exec.Command(\"npm\", \"install\")
log.Printf(\"Running command and waiting for it to finish...\")
err
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
}
}
}
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
}
}
}