Searches like golang interactive cli, golang prompt for input, go interactive cli, or simply go prompt usually mean one of two things: line-at-a-time stdin prompts with the standard library (bufio, fmt, os), or the third-party line editor module often called go-prompt (github.com/c-bata/go-prompt, sometimes typed go.prompt or go/prompt). This page shows the stdlib approach so you can ship an interactive CLI golang tool without extra dependencies; at the end we point to Survey and go-prompt when you need menus, multi-select, or rich TUI behavior.
Tested with Go 1.24 on Linux.
Single-line golang prompt (stdin)
Standard input (stdin) is the stream your process reads when the user types in the terminal. Read until a newline (newline), trim spaces with strings.TrimSpace, and print the label on os.Stderr so it still shows if os.Stdout is redirected.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func namePrompt(label string) string {
r := bufio.NewReader(os.Stdin)
for {
fmt.Fprint(os.Stderr, label+" ")
s, err := r.ReadString('\n')
if err != nil {
return ""
}
s = strings.TrimSpace(s)
if s != "" {
return s
}
}
}
func main() {
name := namePrompt("Enter your name:")
fmt.Printf("Hello %s, welcome to GoLinuxCloud!\n", name)
}Run it locally (go run .) and type a name at the prompt; you should see a greeting with the same text. {run=false} avoids the site Run button here because stdin is not available in that environment the same way as on your machine.
Multiple questions and yes/no (go prompt patterns)
Reuse the same reader pattern for several fields. For yes/no, loop until the answer is recognized instead of treating unknown input as “no”.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func linePrompt(label string) string {
r := bufio.NewReader(os.Stdin)
for {
fmt.Fprint(os.Stderr, label+" ")
s, err := r.ReadString('\n')
if err != nil {
return ""
}
s = strings.TrimSpace(s)
if s != "" {
return s
}
}
}
func yesNoPrompt(label string) bool {
r := bufio.NewReader(os.Stdin)
for {
fmt.Fprintf(os.Stderr, "%s (y/n) ", label)
s, err := r.ReadString('\n')
if err != nil {
return false
}
switch strings.ToLower(strings.TrimSpace(s)) {
case "y", "yes":
return true
case "n", "no":
return false
}
fmt.Fprintln(os.Stderr, "Please answer y or n.")
}
}
func main() {
name := linePrompt("Enter your name:")
nationality := linePrompt("Enter your nationality:")
color := linePrompt("Enter your favourite color:")
pet := linePrompt("Enter your favourite pet:")
fmt.Printf("Hello %s from %s. Favourite color %s, pet %s.\n", name, nationality, color, pet)
if yesNoPrompt("Is this tutorial helpful?") {
fmt.Println("Thank you!")
} else {
fmt.Println("Thanks for the feedback.")
}
}Run locally; you should be able to walk through each question and get a coherent summary plus the follow-up branch.
Loop with numeric guess (fmt.Scanln)
For quick numeric input, fmt.Scanln scans typed tokens into variables; it stops at newline. In modern Go the global random source is seeded automatically, so use rand.Intn(100) + 1 for a secret from 1 to 100 inclusive (the old rand.Intn(1, 100) call is not valid Go).
package main
import (
"fmt"
"math/rand"
)
func main() {
secret := rand.Intn(100) + 1
var guess int
fmt.Println("Guess a number between 1 and 100")
for {
if _, err := fmt.Scanln(&guess); err != nil {
fmt.Println("Please enter a number.")
continue
}
if guess == secret {
fmt.Println("Congratulations, the secret number is:", guess)
return
}
if guess > secret {
fmt.Println("Guess a smaller number")
} else {
fmt.Println("Guess a bigger number")
}
}
}Play a few rounds locally; hints should move toward the secret.
Validate input (why string first, then strconv)
Scanln into an int can turn bad input into 0 without a clear error. Read a line (or token as string), then strconv.Atoi; loop until parsing succeeds. More on conversions: Go cast and parsing.
package main
import (
"fmt"
"strconv"
)
func main() {
fmt.Println("Enter a number:")
for {
var s string
if _, err := fmt.Scan(&s); err != nil {
fmt.Println("Could not read input")
return
}
i, err := strconv.Atoi(s)
if err != nil {
fmt.Println("Enter a valid integer")
continue
}
fmt.Println("Your input number is:", strconv.Itoa(i))
return
}
}Try typing letters, then a valid integer; only the integer path should print the confirmation.
When to reach for a library (Survey, go-prompt)
Stdlib prompts are enough for many CLIs. For multi-select, password masking, or polished surveys, AlecAivazis/survey is widely used. For a Vim-like line editor, completions, and async TUI input, the c-bata project (github.com/c-bata/go-prompt) is what people often mean by go-prompt in module form—add it with go get inside your module, not mixed up with stdin line reading above.
Summary
This article covered golang prompt for input patterns that power an interactive CLI golang tool: line prompts with bufio and os.Stderr, multi-field flows, fmt.Scanln loops for numbers (with a correct rand.Intn range), and string-then-strconv validation so bad typing does not silently become zero. That is distinct from the github.com/c-bata/go-prompt library people sometimes label go.prompt or go/prompt; choose stdlib for simplicity and add a dependency when you need richer UX.

