Go Serverless: Part 1 Google Cloud Functions

Running Serverless Functions with Golang

Go is the most popular language for cloud computing and serverless is becoming more popular for all kinds of workloads. Let´s have a look on how to run a simple Go function on the different cloud providers.

We will start with with Google Cloud Functions and Firebase. AWS Lambda is the most popular serverless platform today. Some providers resell AWS Lambda with nicer/easier tooling and different pricing. We will have a look at Zeit Now and probably “bare-metal” AWS Lambda in this series.

For testing the different providers we will use my tiny project Gistdirect which is a simple HTTP function that redirects to URLs saved in a Github Gist. This project is simple to build and deploy. The Gistdirect function waits to be called with a path to redirect to the given URL.

The beauty of Go (in functions)

I like to use Go for serverless because basically all platforms are expecting standard Go handler functions like this: func Handler(w http.ResponseWriter, r *http.Request). This means you can build your functions reusable for all kinds of handlers like the standard http package or routers like mux. I don’t like building stuff that only works in a particular (cloud) environment. Gistdirect runs standalone as well thanks to a simple main package.

Google Cloud Functions

Since January 2019 Google Cloud functions support Go and combined with Firebase hosting we can get Gistdirect running on its own domain pretty easily.

Obviously you need a Google account and sign up for Google Cloud (GCP). In the cloud console we create a new project. After creation we switch to the Cloud functions menu item and activate the API. After that we could click a button to create a new function, set the runtime to Go, set the environment variable to the Gist URL and paste or upload the code from function.go. But we will use the gcloud CLI tool which is more convenient for frequent updates and testing:

  • Setup gcloud CLI: Quick start
  • Select a project: gcloud config set project NAME
  • Get the Gistdirect project from Github: git clone https://github.com/niklasmerz/gistdirect && cd gistdirect
  • Have a look at function.go: The function Handler(..) contains the redirect code and should be called as entry point.
  • Deploy function for runtime Go 1.11 with the enviroment variable needed for Gistdirect and the entry function Handler CLI command: gcloud functions deploy gistdirect --entry-point Handler --trigger-http --runtime go111 --set-env-vars "GIST_URL=https://gist.github.com/NiklasMerz/a9b5905f742b5863197a0af0465a39f6/raw/"

If everything worked, we will get a result like this:

deploying function (may take a while - up to 2 minutes)...done.                                                                             
availableMemoryMb: 256
entryPoint: Handler
environmentVariables:
  GIST_URL: https://gist.github.com/NiklasMerz/a9b5905f742b5863197a0af0465a39f6/raw/
httpsTrigger:
  url: https://us-central1-PROJECT.cloudfunctions.net/gistdirect
labels:
  deployment-tool: cli-gcloud
name: projects/serverless-blog-236916/locations/us-central1/functions/gistdirect
runtime: go111

Now we can hit https://us-central1-PROJECT.cloudfunctions.net/gistdirect/repo in a browser and we will get redirected to the Gistdirect repo because the test hostfile we set to the environment variable, has this redirect rule.

That’s it our serverless functions is running on GCP!

Bonus get a nicer URL

The whole point of gistdirect to redirect from short URL to longer one. That’s why we want to point our own domain to the function. We can do that with Firebase.

  • Go to the Firebase console
  • Go to “Hosting” in the menu
  • Click “Get started” and install the Firebase CLI tool via NPM
  • Just before we go on to setup our local project we can add our custom domain or sudomain to firebase. We follow the instructions to verify and add the domain. I had some trouble getting the DNS records right the first time, but it should work pretty straightforward.
  • cd into the Gistdirect project directory
  • Use firebase login only and not firebase init
  • We can switch to our project with firebase use PROJECTID
  • Have a look at firebase.json
{
  "hosting": {
    "public": "public",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
        {
            "source": "*",
            "function": "gistdirect"
        }
    ]
  }
}
  • We define here that all our requests to our Firebase domain (https://PROJECTID.firebaseapp.com/) or custom domain should get redirected to our Cloud Function. We just need to set the name of our function and call firebase deploy to set it up. Because Firebase does not support Go functions right now we need to take the longer route and set up our functions with GCP.
  • You can find more information here.

Attention: The function and the Firebase project must live in the same region. My projects are set to us-central1. But you could try other regions.

Now we are ready to go to use serverless functions with our domain