Skip to content

Instantly share code, notes, and snippets.

@albrow
Last active April 16, 2023 03:03
Show Gist options
  • Save albrow/5882501 to your computer and use it in GitHub Desktop.
Save albrow/5882501 to your computer and use it in GitHub Desktop.
Go (golang): How to ask for user confirmation via command line
import (
"fmt"
"log"
"os"
"sort"
)
// 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)
}
@DeveloperMeier
Copy link

okayResponses := []string{"y", "Y", "yes", "Yes", "YES"}
nokayResponses := []string{"n", "N", "no", "No", "NO"}

Can be simplified by lowercasing the first character of the string and comparing to either "y" or "n".

@ZacharyJacobCollins
Copy link

^^

@r0l1
Copy link

r0l1 commented Aug 3, 2016

This is a better way to do the same.

@julienbornstein
Copy link

@r0l1 404

@orirawlings
Copy link

Fixed gist link for @r0l1's solution

@riptl
Copy link

riptl commented Feb 20, 2019

@r0l1 Necropost, but this Gist is still better. It uses fmt.Scanln instead of buffo.NewReader. Yours could read too much from stdin and discard input.

@MavenOfCode
Copy link

MavenOfCode commented May 14, 2019

Actually @albrow, I think you could combine your last two functions like so:

func containsString(slice []string, element string) bool {
	for _, elem := range slice {
		if elem == element {
			return true
		}
	}
	return false
}

@via-justa
Copy link

Or even better

func askForConfirmation() bool {
	var response string

	_, err := fmt.Scanln(&response)
	if err != nil {
		log.Fatal(err)
	}

	switch strings.ToLower(response) {
	case "y", "yes":
		return true
	case "n", "no":
		return false
	default:
		fmt.Println("I'm sorry but I didn't get what you meant, please type (y)es or (n)o and then press enter:")
		return askForConfirmation()
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment