package main import ( "errors" "fmt" "os" "runtime" "time" log "github.com/sirupsen/logrus" ) var ErrGoTimeout = errors.New("GoTimeoutFunc") func GoFunc(f func() error) chan error { ch := make(chan error) go func() { ch <- f() }() return ch } func GoTimeoutFunc(timeout time.Duration, f func() error) chan error { ch := make(chan error) go func() { var err error select { case err = <-GoFunc(f): ch <- err case <-time.After(timeout): log.Debugf("timeout: %v", f) ch <- ErrGoTimeout } }() return ch } func GoTimeout(f func() error, timeout time.Duration) (err error) { done := make(chan bool) go func() { err = f() done <- true }() select { case <-time.After(timeout): return ErrGoTimeout case <-done: return } } func IsDir(dir string) bool { fi, err := os.Stat(dir) return err == nil && fi.IsDir() } func UserHomeDir() string { if runtime.GOOS == "windows" { home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") if home == "" { home = os.Getenv("USERPROFILE") } return home } return os.Getenv("HOME") } // askForConfirmation uses Scanln to parse user input. A user must type in "yes" or "no" and // then press enter. It has fuzzy matching, so "y", "Y", "yes", "YES", and "Yes" all count as // confirmations. If the input is not recognized, it will ask again. The function does not return // until it gets a valid response from the user. Typically, you should use fmt to print out a question // before calling askForConfirmation. E.g. fmt.Println("WARNING: Are you sure? (yes/no)") func askForConfirmation() bool { var response string _, err := fmt.Scanln(&response) if err != nil { log.Fatal(err) } okayResponses := []string{"y", "Y", "yes", "Yes", "YES"} nokayResponses := []string{"n", "N", "no", "No", "NO"} if containsString(okayResponses, response) { return true } else if containsString(nokayResponses, response) { return false } else { fmt.Println("Please type yes or no and then press enter:") return askForConfirmation() } } // You might want to put the following two functions in a separate utility package. // posString returns the first index of element in slice. // If slice does not contain element, returns -1. func posString(slice []string, element string) int { for index, elem := range slice { if elem == element { return index } } return -1 } // containsString returns true iff slice contains element func containsString(slice []string, element string) bool { return !(posString(slice, element) == -1) }