Build a Basic Real-Time Competition App With Go
An end-to-end implementation
Most of us love knowledge contests, right? There are many applications to slake our thirst by making us answer questions coming from different professions.
In this article, I will explain how I implemented a real-time competition app with Golang.
Application Flow

There are some business rules needed to follow.
- When the number of connected users reaches two, the competition will start automatically within 3 seconds.
- There are three states in our competition. These are
NOT_STARTED
,STARTED
,FINISHED
. - Questions have four options, and Users must answer a question within 10 seconds.
- After the competition ends, the leaderboard is shown to users to see the results of the competition.
My Architecture Decisions
In this section, I will try to explain why I made some decisions and try to develop some points of view on our project before we begin. This section will be like a movie spoiler. 🎥
- Websocket is the essential protocol for implementing real-time applications. It provides bidirectional communication between client and server. There are many technical articles to introduce its concepts, so that I won't go into details. I used it to send questions and get connected users' answers.
- I used a unique id (like session-id) for each connected user. In doing so, I can easily differentiate users. In our case, we store our users with their session IDs, and our server manages read and write operations using them.
- To support concurrent read and write operations, I used
sync.Map
. I used sessionID as the key and Client struct as the value shown below. The client structs consist of two fields a clientWebSocket
connection to write and read and totalScore to calculate the leaderboard.

- Broadcast is a special term to represent a method of transferring a message to all recipients simultaneously. Unfortunately, there is no broadcast method in gorilla/websocket; therefore, we will use our custom broadcast method to send messages to all users.

- To send questions to our users, we need to define a model. In our application, I don't want to use the
Question
struct because it has thecorrect_answer
field. I want to hide this information from the connected users, so I created another model calledQuestionDTO
, as shown below.

Competition Flow
I used to manage competition flow with RunCompetition()
method as shown below.
I invoked this function with the main flow of the application by creating a goroutine.
There are three CompetitionState
in RunCompetition()
method.
CompetitionNotStartedState
: To start the competition, there must be two users. When thenumberOfClients
is equal to 2, the state is changed asCompetitionStartedState
.CompetitionStartedState
: In this state, we send questions to all connected users every 10 seconds.
When sending questions, we convert our Question struct to questionDTO
to hide correct_answer
from the connected users to prevent cheating.
After 10 seconds, we change IsTimeout
as true because the time given to the question is up.
CompetitionFinish
: After all the questions are sent,CompetitionState
is changed toCompetitionFinish
. We must create and sendLeaderBoard
to all connected users when the competition is over.
Handle Client Answer Flow
We need to get answers from users to check and calculate their scores.
Users can get a score (+10) when they correctly answer the question within the specified time interval.
There are some important points here:
IsTimeout
: specified time interval- Comparison
question.ID
andClientMsg.QuestionId
: determine whether it is asked question - Comparison
ClientMsg.Answer
andquestion.CorrectAnswer
: determine whether the user gives the correct answer.
After these conditions are met, the score of the user is stored on the map by using sessionID
. We invoke this function in our ws()
method.
To keep our application simple, the competition will start with two users. If the user’s number is greater than two, our app will send http.StatusBadRequest
to user.
Source Code
Thank you for reading. If you want to read my previous articles, you can reach their links below.