#Reading in Console Input in Golang
This is a quick and simple tutorial on how to read in console text input into
your Go (GoLang) program. This tutorial has been updated for Go 1.26 and covers
modern approaches for console input. We’ll be creating the basis for a very simple
shell that will take in all user input and simply echo it back to the user. We’ll
focus on modern approaches using bufio.Scanner and fmt functions.
Reading in Full Sentences
We’ll use Go’s while loop equivalent of a for loop without any parameters to
ensure our program continues on forever. In this example every time text is
entered and then enter is pressed, we assign text to equal everything up to and
including the \n special character. If we want to do a comparison on the
string that has just been entered then we can use the strings.Replace method in
order to remove this trailing \n character with nothing and then do the
comparison.
Note - If you want this to work on Windows Systems then you will have to do
text = strings.Replace(text, "\r\n", "", -1)as windows uses a different line ending compared to unix systems.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Println("Simple Shell")
fmt.Println("---------------------")
for {
fmt.Print("-> ")
text, _ := reader.ReadString('\n')
// convert CRLF to LF
text = strings.Replace(text, "\n", "", -1)
if text == "hi" {
fmt.Println("hello, Yourself")
}
}
}
You’ll see in this example that whenever we enter the word “hi”, our program will print out hello back.
Reading Single UTF-8 Encoded Unicode Characters
If you want to simply read one unicode character from the command line then I recommend you use bufio.ReadRune like so:
reader := bufio.NewReader(os.Stdin)
char, _, err := reader.ReadRune()
if err != nil {
fmt.Println(err)
}
// print out the unicode value i.e. A -> 65, a -> 97
fmt.Println(char)
switch char {
case 'A':
fmt.Println("A Key Pressed")
break
case 'a':
fmt.Println("a Key Pressed")
break
}
Using Bufio’s Scanner (Modern Approach)
The bufio.Scanner is the modern, idiomatic way to read input from the console in Go. It’s the recommended approach for most use cases as it automatically handles line splitting and provides clean error handling.
func scanner() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Println("Error reading input:", err)
}
}
The above code will infinitely ask scan for input and echo back whatever is entered. Notice the proper error handling with scanner.Err() to catch any reading errors.
Understanding os.Stdin and How Input Functions Relate
os.Stdin is the standard input stream for your Go program. It represents the input coming from the user’s terminal or from pipes/redirects. All the input reading methods discussed (bufio.Scanner, bufio.Reader, and fmt functions) ultimately read from os.Stdin or a wrapper around it. When you use bufio.NewScanner(os.Stdin), you’re creating a scanner that reads directly from standard input.
Using fmt.Scan and fmt.Scanln for Structured Input
For simpler use cases where you need to read individual values or structured data, the fmt package provides convenient functions:
package main
import (
"fmt"
)
func main() {
// fmt.Scan reads space-separated values
var name string
var age int
fmt.Print("Enter name and age: ")
fmt.Scan(&name, &age)
fmt.Printf("Hello %s, age %d\n", name, age)
// fmt.Scanln reads an entire line
var input string
fmt.Print("Enter a line: ")
fmt.Scanln(&input)
fmt.Printf("You entered: %s\n", input)
}
fmt.Scan reads space-separated values until a newline, while fmt.Scanln reads an entire line up to the newline character. These functions are useful for quick input handling in simple programs, though for complex input parsing, bufio.Scanner is generally preferred.
Conclusion
As you can see there are numerous ways to do this and the best solution depends
on your particular needs. For most modern Go programs, bufio.Scanner is the recommended approach as it’s idiomatic, handles line splitting automatically, and provides proper error handling. If you only need single character input, use ReadRune(). For simple structured input, the fmt.Scan functions are convenient. If you are wanting to read in full new line delimited sentences with more control, bufio.Reader.ReadString() is still available.
I hope you found this tutorial useful and if you have any further questions then please let me know in the comments section below!
Further Reading
For more related topics, explore making HTTP requests to handle user input for API interactions, or learn about parsing JSON to process structured data from console input. You might also find executing system commands useful when you need to combine console input with system operations.
Continue Learning
Parsing JSON files With Golang
In this tutorial we examine the encoding/json go package and how to parse JSON files.
Executing System Commands With Golang
Executing system commands can be incredibly useful no matter what sort of software you are building,
Go JSON Tutorial
In this tutorial, we are going to cover everything you need when it comes to working with JSON in Go.
Build a Go Serverless App in 5 Minutes With Sst
In this video, we are going to look at what it takes to build a serverless application in Go in 5 minutes using SST.