Boilerplate for writing Go applications without framework using hexagonal application development approach

Simple Gopher

Introduction

You'd probably want to check out ARCHITECTURE.md file to learn more on the architecture of the project layout.

Partial example of a service using hexagonal architecture approach with Go package oriented design. This serves as an example how to design Go services without a framework, high decoupling and easy testability. The example isn't 100% completed or fully covered, but good enough example on how it should look like. It will probably gain more polishing as there is always stuff to be added or updated, but for now, lets start with this.

Bellow is an example of how the README.md file for the service should look like.

Go

Description

Won't get too much into the service itself, it's for you to discover and isn't too important, but to keep it shot, the Simple Gopher is a web API service that integrates with image resize service for resizing images and storing that data and integrates with AWS Cognito for authentication.

Table of contents

Configuration

Configuration of the application is done through the environment variables, which are following:

Required environment variables:

Environment variable name Required Description
PORT Optional Default value is 3000
DEBUG_ROUTES Optional Default value is false, set to true for local endpoint debugging
AWS_REGION Required Example: eu-central-1
AWS_USER_POOL_ID Required Example: eu-central-1_somenumber
AWS_ACCESS_KEY_ID Required AWS IAM key id used for API to talk with AWS services
AWS_SECRET_ACCESS_KEY Required Secret for the above key
DATABASE_URL Required Example postgresql://postgres:example@localhost/db?sslmode=disable
IMAGES_API_DOMAIN Required Endpoint for the image service API
CORS_ALLOW_ORIGINS Required List of origins to allow CORS in format: first.com, second.com, etc.com
SQS_POST_AUTH_URL Required Url of the SQS queue
SQS_POST_AUTH_INTERVAL_SEC Optional Interval in which the API will pool the queue for user registration events. Default value is 600
SQS_POST_AUTH_CONSUMER_DISABLED Optional Default value false, set value to true to turn off in modes like local development to avoid messing with production
BASIC_AUTH_REALM Optional Name of the realm for authentication, default is Forbidden
BASIC_AUTH_USERNAME Optional Username used for basic authentication
BASIC_AUTH_PASSWORD Optional Password used for basic authentication
OAUTH2_AUTHORIZATION_CODE_URL Optional Url for OAuth2 authentication in format https://your-domain.auth.eu-central-1.amazoncognito.com/login?response_type=code&client_id= &redirect_uri=
OAUTH2_TOKEN_URL Optional Url for OAuth2 token retrieval in format https://your-domain.auth.eu-central-1.amazoncognito.com/oauth2/token
DOMAIN Optional Name of the domain the app is being served from, like localhost:3000 or https://your-domain.herokuapp.com

Developing

Development requirements

  • Go v1.17
  • PostgreSQL
  • Docker and docker-compose

You will need to create a new aws cli profile locally and use it with credentials for this API. To create it execute aws configure --profile your-profile then export AWS_PROFILE=your-profile

Running locally

  1. Set the environment variables. It's also recommended storing them in .env file which is ignored for ease of management. Export variables in each row like export MY_VARIABLE=1234, then load the env variables with source .env
  2. Ensure that you start the database and all the other required services by running: docker-compose up -d
  3. After setting the environment variables, execute the make start command to build and start the server

Dependency management

  • Remove dependency by removing all occurrences of the library in imports and execute:
    go mod tidy

Open Api 3 documentation

Golang implementation of OpenApi3 specification aka Swagger through dynamic configuration with Swagger UI.

We use Swagger-UI with some small changes in order for it to fetch changes from our API where we can set the redirection url for OAuth2.

Dependencies

  • github.com/getkin/kin-openapi/openapi3
  • github.com/getkin/kin-openapi/openapi3gen

Documentation is added/updated in src/api/http-transport/openapi3.go, served via src/api/http-transport/handler_openapi3.go with swagger UI located in src/api/http-transport/docs.

Testing

Test configuration

Ensure that you set the DATABASE_TEST_URL environment variable, reason for new one is for safety reasons.

export DATABASE_TEST_URL=postgresql://postgres:example@localhost/db?sslmode=disable

# Also, disable the pooling, we don't need it for testing
export SQS_POST_AUTH_CONSUMER_DISABLED=true

Unit testing

  • make verify

Integration testing

Unit testing with integration testing

  • export TEST_INTEGRATION=true
  • make verify

Vetting

Go provides a great tool for checking out code and detecting possible bugs, think of it as a linter. To run it execute:

make vet

Testing in CI/CD

Ensure that you run the migrations before running end-to-end tests. TBD: create separate e2e test execution

Migrations

Migration requirements

To run the migrations, you must set the database connection url through environment variable:

export DATABASE_URL=postgresql://postgres:example@localhost/db?sslmode=disable

Note that the sslmode=disable is for local development only, for production you should use ssl encryption.

Running migrations

BE CAREFUL WHEN REVERTING! Migrations are done with Go library golang-migrate/migrate and are executed with following commands:

  • make migrate_up to update the schema to the latest
  • make migrate_up_step to update the migration one step up
  • make migrate_down to revert the schema one step down

It's paramount to follow best practices to ensure you don't break anything.

Migrations in CI/CD

For CI/CD ensure that you always run migrations before deploying your new app, like a pre-run action. For rollbacks, also ensure that you first close the application before running the migration down command. As always, for specific cases you will need to pay attention if you need code that supports both versions, so it doesn't crash if the change is drastic.

CI/CD

CI/CD is currently on the Heroku and additional options that were added for it are located in go.mod file as:

  1. Build phase
// +heroku goVersion 1.17
// +heroku install ./cmd/...
  1. Run phase in Procfile

They specify the Go version and build location. Builds will end up in bin/ directory. Other thing to note is that the bin/go-post-compile and bin/go-pre-compile will execute if they exist, so use them for pre and post actions.

Deploying to CI/CD

It is recommended to execute both unit and integration tests, as well as building the app before pushing to git.

# Test
export TEST_INTEGRATION=true
make test
make

More about Heroku options can be found at the Go Buildpack.

Troubleshooting

  • Error when building: open /usr/local/go/pkg/darwin_amd64/runtime/cgo.a: permission denied
    sudo chmod -R 777 /usr/local/go
  • How to clear test cache? Execute go clean -testcache

Helpful materials

Advanced materials

Owner
Marko Kovačević
Software engineer
Marko Kovačević
Similar Resources

Code solution for question against internship application at Eluvio

Eluvio Problem Statement Imagine you have a program that needs to look up information about items using their item ID, often in large batches. Unfortu

Feb 5, 2022

📁 Examples for 🚀 Fiber - Express inspired web framework written in Go

📁 Examples for 🚀 Fiber - Express inspired web framework written in Go

Dec 29, 2022

This project is a GO Restful API service with Gin framework and Gorm SQLite with authorization

GO Restful API service with Gin framework and Gorm SQLite Template Structure Gin is a web framework written in Go (Golang). It features a martini-like

Oct 24, 2022

This tutorial walks you through using the Cloud Functions minimal instances feature to mitigate cold starts.

This tutorial walks you through using the Cloud Functions minimal instances feature to mitigate cold starts.

Tutorial This tutorial walks you through using the Cloud Functions minimal instances feature to mitigate cold starts. Let’s take a deeper look at min

Jun 1, 2022

Cook amazing genetic parts using our cookbook. Recipes and synthetic biology tools to take your breath away.

friendzymes-cookbook Friendly tools for a friendly community. A collection of tutorials and genetic tools for synthetic biology. This cookbook is a su

Aug 19, 2022

This is an example of a keep-it-simple directory layout for Go projects that was created using DDD principles, please copy and share if you like it.

DDD Go Template This project was created to illustrate a great architectural structure I developed together with @fabiorodrigues in the period I was w

Dec 5, 2022

Program that checks if the switch OLED is available on Nintendo using ChromeDP.

Nintendo Switch OLED stock checker Program that checks if the switch OLED is available on Nintendo using ChromeDP. It will check the pages for the Add

Nov 29, 2021

Check-location - A golang service to check user location using their IP address

this is a golang service to check user location using their IP address. The purp

Aug 29, 2022

A demo of using Go channels as a function composition technique.

Channels Example This is a Go program containing functions that consume and produce channels. I think this is potentially a nicer API shape than e.g.

Jan 16, 2022
Learn how to write webapps without a framework in Go.

This is an easy to understand example based tutorial aimed at those who know a little of Go and nothing of webdev and want to learn how to write a webserver in Go. You will create a to do list application as you advance the chapters.

Dec 28, 2022
7 days golang programs from scratch (web framework Gee, distributed cache GeeCache, object relational mapping ORM framework GeeORM, rpc framework GeeRPC etc) 7天用Go动手写/从零实现系列

7 days golang programs from scratch README 中文版本 7天用Go从零实现系列 7天能写什么呢?类似 gin 的 web 框架?类似 groupcache 的分布式缓存?或者一个简单的 Python 解释器?希望这个仓库能给你答案

Jan 5, 2023
Simple boilerplate code to get started with building and deploying a serverless CRUD API

Simple boilerplate code to get started with building and deploying a serverless CRUD API with Go, MongoDB and Netlify

Jan 20, 2022
This is my first golang project. The main reason for its existence is the need for practice. I will be studying golang while writing this project

My first GoLang project Project Aim The goal of this project is to develop the most simple golang bot to learn how to work with this programming langu

Jan 7, 2022
Dec 7, 2021
📖 A little guide book on Ethereum Development with Go (golang)
📖 A little guide book on Ethereum Development with Go (golang)

?? A little guide book on Ethereum Development with Go (golang)

Dec 29, 2022
Test-Driven Development code kata in Golang

Bowling Kata Golang Test-Driven Development code kata in Golang Bowling Rules The game consists of 10 frames. In each frame the player has two rolls t

Jan 5, 2022
roguelike tutorial in Go using the framework gruid

Gruid Go Roguelike Tutorial This tutorial follows the overall structure of the TCOD Python Tutorial, but makes use of the Go programming language and

Jul 25, 2022
Example repository for embedding Litestream in a Go application.

Litestream as Library This repository is an example of embedding Litestream as a library in a Go application. The Litestream API is not stable so you

Dec 6, 2022
Repository for COMP 429 Programming Assignment# 1 - A simple chat application, by Sabra Bilodeau.

Chatty COMP 429 Programming Assignment 1 A Chat Application for Remote Message Exchange by Sabra Bilodeau Getting Started with Chatty Building the Pro

Nov 28, 2021