package main import ( "bufio" "os" "strconv" "strings" "time" ) const defaultMenuAutoServeTimeout = 10 * time.Second // menuAutoServeTimeout 交互菜单自动进入常驻的超时;可由 MENU_AUTO_SERVE_TIMEOUT_SEC 覆盖。 func menuAutoServeTimeout() time.Duration { v := strings.TrimSpace(os.Getenv("MENU_AUTO_SERVE_TIMEOUT_SEC")) if v == "" { return defaultMenuAutoServeTimeout } sec, err := strconv.Atoi(v) if err != nil || sec <= 0 { return defaultMenuAutoServeTimeout } return time.Duration(sec) * time.Second } // readLineTimeout 在 timeout 内等待一行;超时返回 timedOut=true。 // 注意:Windows 控制台无法在超时后取消阻塞读,后台 goroutine 仍会等到用户按 Enter。 func readLineTimeout(r *bufio.Reader, timeout time.Duration) (line string, timedOut bool) { ch := make(chan string, 1) go func() { s, _ := r.ReadString('\n') ch <- s }() select { case s := <-ch: return strings.TrimSpace(s), false case <-time.After(timeout): return "", true } } // serveConfirmYes 是否启动定时常驻(超时视为确认)。 func serveConfirmYes(confirm string, timedOut bool) bool { if timedOut { return true } c := strings.TrimSpace(strings.ToLower(confirm)) return c != "n" && c != "no" }