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:
You need to have Go installed on your computer. You can visit the official Go website to view installation instructions for your operating system.
Create a new directory anywhere on your filesystem, and change into it with the commands below:
Next, initialise your project with a
go.mod file. Replace
<username> with your GitHub username.
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.
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.
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.
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.
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 (
max) and assigning the values 1 and 100 to them respectively. The
max variables represent the range within which the random number will be generated.
Here’s where we generate a secret number within the
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
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
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.
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:
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
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
Try running the program again. You should get different random numbers, and they should all be numbers between 1 and 100.
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:
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
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.
The above line of code declares a new variable called
reader and initialises it to the return value of
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() 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
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.
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
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
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.
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:
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
Run the program a few times to verify that the code works as expected.
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.
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.
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
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.
Let’s wrap up the game by deleting the line that prints out the
secretNumber to the screen. The final code is shown below:
Congratulations! You’ve successfully created a guessing game in Go and learnt many new concepts such as variables, loops, functions, control flow, error handling and more along the way.
If you have any questions, please leave a comment below and I’ll get back to you. Thanks for reading!