#Reading in Console Input in Golang

Elliot Forbes Elliot Forbes · Mar 7, 2026 · 4 min read

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.