Understanding Go User Input Methods
Abdullah Alaadine
Go Backend Developer | Building Scalable, High-Performance Systems | Passionate About Open Source & Developer Tools
Handling user input in Go can be a bit confusing, with various methods available for different purposes. In this article, we'll categorize these methods into four distinct groups to simplify the understanding of how to obtain user input effectively:
Reading One Rune (character):
To read a rune from a user, bufio.Reader.ReadRune is a great way to do so, especially if you're going to read rune multiple times. It's well-suited for reading single runes or individual characters when you need to handle Unicode input correctly.
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("enter a rune: ")
r, _, _ := reader.ReadRune()
fmt.Printf("you entered: %c\n", r)
}
Another way is to use fmt.Scanf, which I think it's easier if you want to read a rune only once.
func main() {
var r rune
fmt.Print("enter a rune: ")
fmt.Scanf("%c\n", &r)
fmt.Printf("you entered: %c\n", r)
}
Note: you cannot directly use fmt.Scan or fmt.Scanln to read a rune because the 'rune' type is just an alias for int32. To obtain user input using these methods, the user must enter the decimal representation of the character, such as 97 for 'a', which is not a good user experience. (in most cases)
Reading One or More Values (words)
When you want to gather specific values, whether it's one or more, these methods come in handy:
func main() {
var name string
var lastName string
fmt.Println("enter your full name")
fmt.Scan(&name, &lastName)
fmt.Println("your full name is:", name, lastName)
}
fmt.Scan(): This method reads values separated by spaces or newlines, assigning them to the provided variables. For instance, if a user types "John Doe," the 'name' variable will be "John," and the 'lastName' variable will be "Doe." Importantly, fmt.Scan() does not raise an error if extra values are entered.
func main() {
fmt.Println("What is your favorite programming language?")
var programmingLanguage string
_, err := fmt.Scanf("%s is my favorite programming language", &programmingLanguage)
if err != nil {
log.Fatal(err)
}
if strings.ToLower(programmingLanguage) != "go" {
log.Fatal("you are not allowed to love programming language other than Go! ??")
}
fmt.Println("haha, I knew that", "Go", "is your favorite programming language ??")
}
fmt.Scanf() is similar to fmt.Scan(), but it expects input in a specific format. If the input format doesn't match, it returns an error.
func main() {
var name string
var lastName string
fmt.Println("enter your full name")
fmt.Scanln(&name, &lastName)
fmt.Println("your full name is:", name, lastName)
}
fmt.Scanln() is similar to fmt.Scan(), but it stops scanning at a newline character. This forces the user to enter their input on a single line.
领英推荐
Reading a Full Line
If your requirement is to read a complete line, you can utilize bufio.Reader or bufio.Scanner struct, let's see some examples:
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Println("hi, what makes Go the best programming language?")
answer, err := reader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
fmt.Printf("mmm, your answer will be saved: '%s'\n", answer)
}
With bufio.Reader, reader.ReadString('\n') reads the entire line, including the newline character. If you want to exclude the newline character, consider using bufio.Scanner instead.
Note: you can use the argument you want instead of '\n', but anyway, the way it works is to read the data up to and containing the argument, which is the delimiter.
Use bufio.Scanner to read full line without the new line character.
func main() {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("hi, tell me about yourself very briefly, in one line")
scanner.Scan()
err := scanner.Err()
if err != nil {
log.Fatal(err)
}
fmt.Printf("mmm, your answer will be saved: '%s'\n", scanner.Text())
}
Reading Multiple Lines of Text
For scenarios where users need to enter multi-line text, such as chat applications, You can use bufio.Scanner or bufio.Reader within a loop. Here's an example of how to read a message with potentially multiple lines:
func main() {
fmt.Println("Input message:")
scanner := bufio.NewScanner(os.Stdin)
var message []string
for {
scanner.Scan()
line := scanner.Text()
if len(line) == 0 {
break
}
message = append(message, line)
}
err := scanner.Err()
if err != nil {
log.Fatal(err)
}
fmt.Println("User message:")
for _, line := range message {
fmt.Println(line)
}
}
This code allows users to enter as many lines as they want, terminating the input by pressing enter on an empty line.
Conclusion
In summary, choose the input method that best suits your needs:
These methods cover the most common scenarios for handling user input in Go. Good luck with your Go programming endeavors!
Experienced Full Stack Developer
1 年The font of the letter in the images is very small for those of us who read the article