Understanding Go User Input Methods

Understanding Go User Input Methods

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:

  • fmt.Scan
  • fmt.Scanf
  • fmt.Scanln

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:

  • Use fmt.Scan or fmt.Scanln for collecting a specific number of words (one or more).
  • Use fmt.Scanf when input must adhere to a specific format.
  • Use bufio.Reader.ReadString to read a full line with the newline character.
  • Use bufio.Scanner to read a full line without the newline character.
  • Use bufio.Reader.ReadRune for reading a single character.
  • For reading multi-line text, use bufio.Scanner or bufio.Reader within a loop.

These methods cover the most common scenarios for handling user input in Go. Good luck with your Go programming endeavors!



Guillermo Rivero

Experienced Full Stack Developer

1 年

The font of the letter in the images is very small for those of us who read the article

回复

要查看或添加评论,请登录

Abdullah Alaadine的更多文章

  • Struct Embedding in Go

    Struct Embedding in Go

    Introduction: Struct embedding is a powerful and versatile concept in Go that enables developers to create more complex…

  • Simplify Execution Time Measurement in Go

    Simplify Execution Time Measurement in Go

    Hello, Today, I'm delighted to bring forth a practical and elegant Go programming technique that shines a light on…

    2 条评论
  • The "Set" Data Structure in Go

    The "Set" Data Structure in Go

    Audience: Go developers (beginners → intermediates) In the realm of programming, data structures are the backbone of…

    8 条评论
  • Demystifying interface{} Usage as a Universal Function Parameter in Go

    Demystifying interface{} Usage as a Universal Function Parameter in Go

    Introduction: Have you ever wondered why Go developers often use the interface{} type as a function parameter to…

社区洞察

其他会员也浏览了