# How to program a guessing game with Go

Let’s jump into Go by working through a hands-on project together. This tutorial will introduce you to a few common Go concepts such as variabes, error handling, loops, packages, and more by showing you how to use them to tackle a classic beginner programming problem.

In this tutorial, we’ll build a “Guess the number” game in Go. In this game, the program will generate a random integer between 1 and 100, and then prompt the player to enter a guess.

After a guess is entered, the program will notify the player if the guess was higher or lower than the random number, and prompt the player for another guess. Otherwise, if the guess is correct, a congratulatory message will be printed on the screen and the program will exit.

The objective here is to give you your first bit of experience with writing a Go program, and for you to gain a basic understanding of what writing a Go program involves.

At the end of this tutorial, you should have a program that works in a similar manner to the demo below: ## Prerequisites

You need to have Go installed on your computer. You can visit the Go website to view installation instructions for your operating system.

## Project setup

Create a new directory anywhere on your filesystem, and change into it with the commands below:

``````\$ mkdir guessing-game
\$ cd guessing-game``````

Next, initialise your project with a `go.mod` file. Replace `<username>` with your GitHub username.

``\$ go mod init github.com/<username>/guessing-game``

Finally, create a `main.go` file in your project root, and open it in your favourite text editor. You will write all the code for this project in this file.

``\$ vim main.go``

## How the game works

As you can observe from the demo, when the program runs, a random integer between 1 and 100 is generated. The player is subsequently prompted to guess what number was generated and feedback is provided to the player if the guess is higher or lower than the secret number. If the guess is equal to the secret number, a congratulatory message is printed and the program exits.

Let’s start by generating a random number between 1 and 100 in the next section.

## Generate a random number

To generate a random number, we’ll be making use of the `math/rand` package from the standard library. Modify your `main.go` file shown below:

Let’s go over the code line by line. The first step is to declare the package that this file belongs to. In this case, it’s the `main` package. The `main` package is special in Go as it serves as the entry point for every executable program.

``````import (
"fmt"
"math/rand"
)``````

To print text to the terminal, we need to bring the `fmt` package into scope. It provides several methods that we can leverage to print the result of an operation to the standard output. We also need to import the `rand` package before we can use it. When importing more than one package, you can place the package names inside parenthesis. This prevents you from repeating the `import` keyword on every line.

Note that the `rand` package was imported as `math/rand`. This is because it is nested inside the `math` package as a subdirectory. The convention in Go is that package name is the same as the last element in the import path.

``func main(){}``

As discussed in the last article, the `main` function is the entry point to the program. It is called automatically when you run the program.

``min, max := 1, 100``

This above statement represents a short variable declaration in Go and it can only be used inside functions. Here, we’re creating two new variables (`min` and `max`) and assigning the values 1 and 100 to them respectively. The `min` and `max` variables represent the range within which the random number will be generated.

``secretNumber := rand.Intn(max-min) + min``

Here’s where we generate a secret number within the `min` and `max` constraints. The `rand` package exports an `Intn` method that returns a psuedo-random positive number between 0 and its argument which should be a positive integer. In this case, the argument is `99` (`max` - `min`), so the range of numbers that can be generated will be between 0 and 98. `min` is added to the output of `rand.Intn()` so as to change the range to 1…99 instead.

Note that the `max` number is exclusive in the range while `min` is inclusive. If you wanted numbers between 1-100, you have to change the `max` variable to `101`.

``fmt.Println("The secret number is", secretNumber)``

The `fmt` package exposes a `Println` method which prints its arguments to the console and adds a newline at the end. If there are more than one arguments, they are separated with a space.

Save your `main.go` file and run the program in the terminal using `go run main.go`. You should get a similar output to the one shown below:

``````\$ go run main.go
The secret number is 24
\$ go run main.go
The secret number is 24
\$ go run main.go
The secret number is 24
\$ go run main.go
The secret number is 24``````

It appears that the same number is printed to the screen each time. This is definitely not what we want. But why is this happening? There’s a simple explanation.

The numbers that the `rand` package generates are based on a specific initial value called its seed. The default seed is 1, so unless you change it, you’ll always get the same output. The seed needs to be something that’s unique and always changing, so that when the program is run multiple times, you’ll get better random values. A popular choice for this initial seed is the current time in nanoseconds which will most probably be a different value on each execution.

Here’s how to change the initial seed of the `rand` generator:

``````// note that `rand.Seed()` expects an `int64` type so make sure
// that whatever you pass into it produces an `int64` value.
// Also, it needs to be called before any other methods from the
// `rand` package
rand.Seed(time.Now().UnixNano())``````

Here’s how your `main.go` file should look like after adding the code snippet above:

Notice the introduction of the `time` package amongst the imports. This is the package that provides functionality for measuring and displaying time in Go. It exports a `Now()` method that returns the current time and the `UnixNano()` method which returns the number of nanoseconds elapsed since January 1, 1970 UTC as an `int64` value.

Try running the program again. You should get different random numbers, and they should all be numbers between 1 and 100.

``````\$ go run main.go
The secret number is 91
\$ go run main.go
The secret number is 77
\$ go run main.go
The secret number is 84
\$ go run main.go
The secret number is 6``````

## Read user input from the terminal

The next step is to allow the user to enter a guess and then check that it’s in the expected format (that is, it must be an integer).

Here’s the code that helps us achieve that:

Let’s go over each of the new additions so as to understand what they all do:

``````fmt.Println("Guess a number between 1 and 100")

The above lines introduces the game and prompts the player to enter a guess.

The next step is to accept input from the player. The `bufio` and `os` packages are what we’ll be using to capture the user’s input. Notice how they’re both imported at the top of the file.

``reader := bufio.NewReader(os.Stdin)``

The above line of code declares a new variable called `reader` and initialises it to the return value of `bufio.NewReader(os.Stdin)`.

The `NewReader()` method of `bufio` takes a value that implements the  io.Reader interface. `os.Stdin` represents an open File that points to the standard input file descriptor, and also implements the `io.Reader` interface which is why we’re able to pass it as an argument to `NewReader()`.

``input, err := reader.ReadString('\n')``

The `NewReader()` method returns a bufio.Reader struct which has a method called `ReadString()` which takes in a delimiter (the newline character `\n` in this case). This method reads the user’s input until the first occurrence of the delimiter in the string, and returns two values: a string containing the data up to and including the delimiter, and an error (if any). The former is stored in the `input` variable while the latter value (the error) stored in the `err` variable.

``````if err != nil {
return
}``````

The above snippet handles the error that might occur when using the `ReadString` method. This is the idiomatic way to handle errors in Go. Before using the result of ReadString, the error value is checked to see if it’s not `nil`. If so, a message is printed to the screen and the `main` function returns causing the program to exit.

``input = strings.TrimSuffix(input, "\n")``

Assuming `err` is nil, program execution will move to the next line shown above. Remember that `ReadString()` includes the delimiter in the result value. This means that the `input` will contain the newline character in addition to whatever the player entered.

For example, if the player types 30 and presses Enter, the value of `input` will be 30\n. But we don’t want this `/n` part in the input so we need to get rid of it. This can be achieved using the `TrimSuffix()` method from the `strings` package. All we need to do is pass the string and the trailing suffix. It will then return the provided the string without the suffix, so `30\n` will become just `30`.

``guess, err := strconv.Atoi(input)``

The next step we need to convert the `input` string to an integer so that we can compare it numerically to the `secretNumber` variable created in the last section.

To convert a string to an integer in Go, The `Atoi()` method from the `strconv` package is employed. This method attempts to convert the provided string into an integer and returns an integer and an error which are assigned to `guess` and `err` respectively.

``````if err != nil {
fmt.Println("Invalid input. Please enter an integer value")
return
}``````

The usage of `Atoi()` can easily result in an error which must be handled appropriately. For example, if the player’s input contained an alphabet, there would be no way to convert it to an integer. Therefore we need to stop the program and remind the player to provide an integer input.

``fmt.Println("Your guess is", guess)``

But if there is no error, the player’s guess will be printed on the screen.

Save the file and run the program using `go run main.go`. You should get a similar output to the one below:

``````\$ go run main.go
45
Guess a number between 1 and 100
20

## Compare the player’s guess to the secret number

Now that we have both the player’s guess, and the secret number, it’s time to compare them. We’ll provide feedback to the player if the guess is higher or lower than the secret number. If the guess is equal to the secret number, we’ll print out a congratulatory message and exit the program.

Add the following code to the end of your `main` function below the line that prints the `guess` variable:

Run the program a few times to verify that the code works as expected.

``````\$ go run main.go
The secret number is 72
Guess a number between 1 and 100
65
Your guess is smaller than the secret number. Try again
\$ go run main.go
The secret number is 85
Guess a number between 1 and 100
93
Your guess is bigger than the secret number. Try again
\$ go run main.go
The secret number is 78
Guess a number between 1 and 100
78
Correct, you Legend!``````

Our program mostly works but the player can only input one guess, and the program exits regardless of whether the guess is correct or not. Let’s change this behaviour so that the player is able to continue guessing until the correct number is guessed. We will also inform the player of the number of attempts made before winning the game.

Change your `main` function as shown below:

We created a `for` loop above, and moved all the code below the line that prompts the user to input a guess into it.

In Go, using a for loop without a loop condition creates an infinite loop, and the only way to break out of this sort of loop is by using the `break` keyword which we’re doing when the player guesses correctly. This also causes the program to exit.

Notice the `attempts` variable declaration just before the loop. It’s how we keep track of the number of times a player had to guess before making a correct guess. When game is won, the number of attempts is printed in the congratulatory message.

Also note that the error handling from the `Atoi()` and `ReadString()` methods have been changed slightly to use the `continue` keyword in place of `return` to ensure that loop skips to its next iteration when an invalid input is received instead of exiting.

If you run the program now, you’ll be able to play the game and enter several guesses without the program exiting.

``````\$ go run main.go
The secret number is 20
Guess a number between 1 and 100
26
Your guess is bigger than the secret number. Try again
22
Let’s wrap up the game by deleting the line that prints out the `secretNumber` to the screen. The final code is shown below: