A REST API for Conway's Game of Life.
- Go: download
- Air (optional live reload): installation
- Templ (board web view): installation
go mod downloadThe html template needs to be generated the first time, or if page.templ is edited.
templ generateThe entrypoint for the program is in cmd/cmd.go
We can start the server with live reload for local development
airor, run the command directly
go run cmd/cmd.goor, compile the binary and run it
go build -o life-server ./cmd
./life-serverThe OpenAPI spec file details the API endpoints and their expected payloads and outputs.
To create a new board:
curl --request POST \
--url http://localhost:8080/board \
--data '{
"cells": [
[false, false, false, false, false],
[false, false, false, false, false],
[false, true, true, true, false],
[false, false, false, false, false],
[false, false, false, false, false]
]
}'response:
{ "id": 28 }With the returned id, you can now get the current state of the board:
curl --request GET \
--url 'http://localhost:8080/board/{id}'response:
{
"id": 28,
"cells": [
[false, false, false, false, false],
[false, false, false, false, false],
[false, true, true, true, false],
[false, false, false, false, false],
[false, false, false, false, false]
],
"generation": 0,
"final": false
}You can also fetch a board, first advancing its generations one or more times:
curl --request GET \
--url 'http://localhost:8080/board/{id}?state=10'state will default to a maximum value of 1000 if exceeded
response:
{
"id": 28,
"cells": [
[false, false, false, false, false],
[false, false, false, false, false],
[false, true, true, true, false],
[false, false, false, false, false],
[false, false, false, false, false]
],
"generation": 10,
"final": false
}Fetching a board's final state, potentially getting an error if final state not reached in the request number of iterations
curl --request GET \
--url 'http://localhost:8080/board/{id}/final?state=10'response:
{
"id": 27,
"cells": [
[false, false, false, false, false],
[false, false, false, false, false],
[false, false, false, false, false],
[false, false, false, false, false],
[false, false, false, false, false]
],
"generation": 14,
"final": true
}or
{
"error": "final state not reached"
}For convenience in visualizing output, you can also access the GET endpoints via a browser. The resulting page will have a display of the Game of Life grid and a button to advance a generation.
The
Nextbutton will disable if the board is at its final generation.
CORS is allowed on this server, so you can also use VS Code's built-in OpenAPI Editor to make requests.
Run at project root:
go test ./...This was built as a solution to a tech challenge with roughly the following criteria:
- Create an API for Conway's Game of Life
- Allow for the following
- Upload a new board, return its id
- Get next state for a board
- Get x number of states forward for a board
- Get final state for a board
- Server should retain state on restart
This project is built to demonstrate production-ready code, with some tradeoffs or exclusions to keep things reasonable for time and complexity. Otherwise, its structure and design are consistent with how I build HTTP servers in Go.
This was built in Go because it is what I am most proficient in for building a backend/server. It is very well suited for this type of work, with a standard library that has more than enough included.
Non-standard library use of templ and testify are useful to eliminate a lot of boilerplate to be able to quickly give a visual aid and make test assertions. Bolt was used to support data persistence.
To satisfy this need, I wanted to use something as simple as possible, since the data model is very basic. I went with Bolt so that I didn't have to stand up any containers or outside services.
Since it's just another Go dependency in the code, nothing more is required to install to get it working. This is also super helpful for easy testing.
Testing is done by running integration tests against the server as an outside HTTP client. The table of tests will look a lot like unit tests, and the goal is to test each happy path and possible error that could be returned by the server from the perspective of an HTTP client, our intended user. By testing by making calls 'over the wire', we're not excluding any part of our stack and can test in an environment that is nearly identical to a real world production environment.
A few tests are provided to show how it is done, the test cases are not exhaustive. Specifically, tests around the happy path for creating and getting boards exist. Further tests would check things like input validation responses.

