This is still a work-in-progress, the tests are broken.
Table of Contents
- Overview
- Prerequisites
- Getting Started
- Running the service
- Running the testss
- The Case for Why We Should Switch to Go For Our Backends
This is a simple example of a hotel reservation service written in Go. It is aGraphQL API that allows you to create and list reservations as well as the ability to list available rooms for a given date range.
My first attempt at a Golang application. I may have done some unconvential things here.
To run the service, you will need to install the following tools.
- Go Lang
- NodeJS. Used for the Serverless Framework for local development and for migrations.
- nvm. Used to manage NodeJS versions. However, this is optional but I've included an
.nvmrc
file in this repository just in case. - Direnv. Used to manage environment variables.
- Docker. For deploying to AWS Lambda. Actually, to ECR and then to Lambda. With that said, you can skip this if you don't want to deploy. Alternatively, you can use the full extent of the Serverless Framework but that's out of the scope of this README.
First things first, we'll need to set up our environment variables. If you've never used Direnv before, you'll understand it's use soon enough.
cp .envrc.example .envrc
direnv allow
Execute the following within your terminal:
# To eliminate any issues, install/use the version listed in .nvmrc.
# If you need to install the listed version of Node, execute `nvm install <version-listed-in-.nvmrc>`
nvm use
cd ./db
npm i # Install the packages needed for migrations/seeding, knex and pg
Let's create and seed the databases and our Reservations and Rooms tables:
# Create the databases and seed them
NODE_ENV=development | ./create_db.sh && npm run refresh
NODE_ENV=test | ./create_db.sh && npm run refresh
Now, navigate back to the root of the project via cd ..
and execute the following to install the Go packages needed for the service:
go mod tidy
Plus, you'll need to install the following packages *globally:
go install github.com/onsi/ginkgo/v2/ginkgo # install the Ginkgo BDD testing framework
go install github.com/go-delve/delve/cmd/dlv@latest # install the Delve debugger
I should explain what globally means in regards to your Go installation. When you install a package globally, it will be installed in your $GOPATH/bin
directory. In my case, it's /Users/username/go/bin
. You can check your $GOPATH
by executing go env GOPATH
. If you don't have a $GOPATH
set, it will default to $HOME/go
. You can set your $GOPATH
by executing export GOPATH=/path/to/your/go/path
. You can also add this to your .bash_profile
or .zshrc
file. For instance, I have the following in my .bashrc
file:
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
To run the Lambda function locally, we'll use the Serverless Framework's go and offline plugins. We'll install NPM packages locally to do so:
nvm use # optional; you can just use the version of Node listed in .nvmrc
npm i -g serverless serverless-go-plugin serverless-offline
# You'll need to modify the serverless.yml file to use the environment variables in your .envrc file
cp serverless.yml.example serverless.yml
Subsequently, we can run the service locally by executing make run
in the root of the project. Build the GraphQL Playground handler and start the service on ports 8081 and 8080, respectively, or whatever ports the PLAYGROUD_PORT and API_PORT environment variable are set to.
curl http://localhost:$API_PORT/development/api \
-H 'Content-Type: application/json' \
-d 'query GetAllReservations {\n reservations {\n Id\n RoomId\n }\n}'
Viola! Again, you can also acces the non-Lambda function GraphQL playground at http://localhost:$PLAYGROUND_PORT/playground.
In summary, to run the Lambda function and the GraphQL playground locally, execute the following:
docker-compose up -d
make run
You can painlessly debug your service using Delve and it works in VS Code as well.
Delve is a debugger for the Go programming language. It provides GDB-like command-line debugging experience and is much more powerful than the standard Go debugger. To install it, run the following command:
go install github.com/go-delve/delve/cmd/dlv@latest
If you are using VS Code, install the Go extension and add the following configuration to your launch.json
file:
{
"version": "0.2.0",
"configurations": [
{
"name": "Code",
"type": "go",
"request": "launch",
"mode": "debug",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceRoot}",
"env": {},
"args": [],
"showLog": true
},
{
"name": "Test Current File",
"type": "go",
"request": "launch",
"mode": "test",
"port": 2345,
"host": "127.0.0.1",
"program": "${file}",
"env": {},
"args": [],
"showLog": true
}
]
}
You can then start the debugger by pressing F5
or by clicking on the Debug
button in the VS Code sidebar. To make it easier to debug, there is a api/debug.go
file containing functions you can use in main to debug the service. For example, you can change the following in your lambdafunc/main.go
file:
func main() {
// lambda.Start(api.GraphQlApiHandler)
api.DebubGraphQlApiHandler()
}
You can then set breakpoints in VS Code and debug the service with ease.
This project contains BDD style tests with the help of Ginkgo v2. You will need to have Ginkgo installed, something you should have achieved when you followed the Getting Started step. To run the tests, execute the following:
go test ./specs
There are multiple options to deploy the Lambda functions. You can use the Serverless Framework, AWS SAM, AWS CLI, push Docker containers to ECR, or use a custom GitHub Action. Using Docker containers may simplify things but it may lengthen cold start times and add additional costs. Going the GitHub Action route is a more cost-effective route to build and deploy Lambda functions to AWS. Using a GitHub Action to build and deploy your Lambda functions to AWS can be a more cost-effective approach, as it can leverage the existing infrastructure of your GitHub repository and doesn't require additional resources to be provisioned. This approach can also be more flexible and customizable, as you can tailor the deployment workflow to meet your specific needs. See the deployment action workflow for more details of how you would deploy the service. For the example workflow, you'll need to add the following secrets to your GitHub repository: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.