Learning Golang: Scan, Scanln and Scanf

Share on:

This is part 18 of my journey learning Golang.

Command line interface

When building programs that run on a terminal it is often useful to be able to allow the user to enter text.

For instance the ssh-keygen utility will prompt for a path and a passphrase.

1❯ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
2Generating public/private rsa key pair.
3Enter file in which to save the key (/home/fernando/.ssh/id_rsa): /tmp/test_rsa
4Enter passphrase (empty for no passphrase):
5Enter same passphrase again:

Scan

The Scan method of the fmt package will read a single space-separated token (like a single word) from the standard input device (which is usually the console).

Scan expects an address as its argument. That can be provided by using the & symbol in front of a variable name.

For example:

 1package main
 2
 3import (
 4  "fmt"
 5)
 6
 7func main() {
 8  fmt.Print("What is your first name? ")
 9  var response string
10  fmt.Scan(&response)
11  fmt.Printf("Hello, %v!\n", response)
12}

Source: learning-go/scanning/scan.go

This program, when executed, will wait for the user to enter a line of text, and then it will take the first word of that line (until it finds a space or the end of the line):

1❯ go run ./scanning/scan.go
2What is your first name? Jane
3Hello, Jane!

If more than one word is entered, only the first one is read by Scan. The remainder is left in the console and can be read by another Scan call. For example:

1❯ go run ./scanning/scan.go
2What is your first name? Jane Doe
3Hello, Jane!
4
5❯ Doe
6zsh: Doe: command not found...

Notice how the rest of the input was left in the console, and was read by the terminal after the program finished.

Scanln

The Scanln method is similar to Scan. It will also read space-separated tokens. Two differences are:

  • it will stop at a newline character;
  • it requires a newline or EOF character after the last item.

Scanf

According to the documentation:

Scanf scans text read from standard input, storing successive space-separated values into successive arguments as determined by the format. It returns the number of items successfully scanned. If that is less than the number of arguments, err will report why. Newlines in the input must match newlines in the format. The one exception: the verb %c always scans the next rune in the input, even if it is a space (or tab etc.) or newline.

Scanf adds finer-grained control (via a format string) to input parsing.

Reading full lines from the console

If the program requires reading a full line from standard input, instead of using the fmt package it is better to use the bufio package.

This article teaches how to do that: Reading in Console Input in Golang.

Takeaways

The “Scan” family of methods in the fmt package is meant for reading tokens and other kinds of delimited values from standard input.

The bufio package is better suited for interacting with users via a command line interface.


comments powered by Disqus