Multiple Azure functions in Golang

Tomomi Sako
4 min readJan 19, 2022

Azure Functions recently added the Custom Handler feature which gives you more options on which programming language you can use.

In this article, I will focus on how to host multiple Golang Azure Functions in a single Function App and also how to deploy it.

This is an example code: https://github.com/Azure-Samples/azure-function-custom-handler-with-golang

In this example, we have two Azure Functions /drinkand /drinks. /drink can be used to create, update, or delete your favorite drink, and /drinks method to retrieve all the previously saved drinks.

Those Functions share one in-memory storage and can be run in a single Dev container.

It also includes three different pipeline configuration files so that you can easily set up a deployment pipeline.

Directory structure

This is a directory structure for the sample. I have written comments next to the key files that I will describe in this article.

|- .devcontainer
|- devcontainer.json // Settings file for dev container
|- Dockerfile // Docker file for dev container
|- cmd
|- main.go // Entry point
|- drink
|- function.json // Host settings file for drink Function
|- drinks
|- function.json // Host settings file for drinks Function
|- internal
|- drink
|- handler.go // Handler for drink Function
|- drinks
|- handler.go // Handler for drinks Function
|- pipelines
|- .github
|- workflows
|- github-pipeline.yml // Pipeline for GitHub actions
|- .gitlab-ci.yml // Pipeline for Gitlab
|- azure-pipeline.yml // Pipeline for Azure Devops
|- pkg
|- storage
|- storage.go // In-memory storage implementation
|- host.json // Settings file for Azure Function App
|- Makefile // Make command
|- README // Step by step of how to deploy and use

This directory structure basically follows the golang standers project layout.
Some Azure function related files (like host.json) are added to the project.

The entry point is main.go and each Azure function’s handler is under internal directory. The storage logic code is shared between two functions so the logic code is located under pkg.

Dev Container

The .devcontainer directory has two files required to build a devcontainer.

devcontainer.json is a settings file. For example, if you want to add a new extension to VScode you need to update this file.
It mounts .ssh directory so that we can use ssh against a devops platform.

Dockerfile is used to build the devcontainer docker image. The base image is golang:1.17.6-bullseye which is Debian 11. If you want to use a different linux version, please check Azure Functions core tools to see if the version is supported.
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT is required for Azure Functions so please do not remove it.

Azure Functions

The cmd directory has main.go which is the entry point and has routing rules for the Azure Functions.

In theinternal directory, there are drink and drinks directories and each directory has a handler.go. These handler files contain simple logic for CRUD operations on the storage.

This sample uses in-memory storage and the logic is defined in storage/storage.go under pkg.
The in-memory storage is actually a hash map, and this file has some functionality (GET/POST/DELETE) to access it.

Azure Function App host configuration

host.jsonhas settings for the Azure Function App. For example, we use a custom handler as the runtime and specify the binary the Function app will use.

To configure the host information of the individual Azure Functions, we put the details in each function.json. This JSON file lives in a parent directory where the directory name should match with your endpoint.
So in this sample we have two Azure Functions and the endpoints are /drink and /drinks. For the host information file, we can do/drink/function.json and /drinks/function.json.

Pipeline

The pipelines directory has two pipeline yml files, one for Gitlab and one for Azure DevOps. Additionally, it has a pipeline yml for GitHub under .github directory. (This directory structure is required by GitHub Actions)

The pipelines are slightly different depending on the devops platform, but it basically has two stages (Build/Deploy) and the Deploy stage will be triggered when the code is merged to the main branch.

For more information on how to build the pipeline for each devops platform, please refer to the README.

--

--