Cloud Functions in Go

It’s happened! Go is now an officially supported language for Google Cloud Functions (check the blog). Goodbye node.js… for me at least.

Let’s take it for a quick spin with a quick function that uses some shared code to output some JSON.

All of the code for this project at https://github.com/theyakka/go-func-example.

The Code

Let’s create the directory structure first. We will need two folders: one for our common code and one for our functions code. The overall structure will look like this:

+ myfunctions
- common
- functions

To allow our functions to see / use the common code, we’re going to create a local module using the module functionality added in go 1.11. So, under both the common and the functions folders, let’s first create a couple ofgo.mod files.

For simplicity, we’re going to use the module name mysite.com/myfunctions as the base identifier for all of our code. Therefore, the contents of the common/go.mod file should be module mysite.com/myfunctions/common and that’s it.

The functions go.mod is a little more complicated. Here is what it looks like:

Quick breakdown of what is going on here. Using the version number v0.0.0 tells Go that we’re going to be working outside of a VCS system so it shouldn’t try to hit mysite.com/myfunctions/common to check for the latest version and download it. However, we still need to tell Go where to find it, so that’s what we achieve with the replace line. The replace tells Go that it should go to the common folder for the common code. A bit verbose, but it works.

Next, lets set up our first function entry point. Under the functions folder, create a file called message_func.go. Now we need to add a function handler. Let’s call ours OuputMessage:

Now, just for the sake of an example of accessing some common code from our function, let’s add a helper struct that we can pass a message to and it generates & writes a JSON response to our ResponseWriter.

Create a file called json_message_writer.go in a folder called writers under the common module. Now, let’s add some quick and dirty code to produce and write the JSON. The file should look like:

All that we’re doing here is simply taking a string value that is passed into the JSONMessageWriter at creation time, wrapping it in a simple response structure and encoding the map to a JSON string. Pretty simple.

So, now we can update our original function to use the message writer.

To make it a bit more dynamic, we’re pulling the message we’re going to display from the a query string value (called message) and passing that along to our JSONMessageWriter. If there is an error, we’re returning a 500 status code and printing the error to the console/log and writing it as plain text to the ResponseWriter. We would obviously want to make that JSON also but, for now, we’re not going to deal with that.

And that should do it for the code for the moment. Let’s give it a quick test and then move onto deployment.

Testing Locally

To test our function locally we can use a test (which we should be writing anyway). Let’s set up a quick test to test that the function executes correctly (returns a status code 200) and matches the JSON generated by the JSONMessageWriter:

Run the test from your chosen IDE or using the command line (inside the functions directory):

go test -run TestOutputMessage

You should see a PASS like:

PASS
ok mysite.com/myfunctions 0.003s

This means we’re now good to move onto deployment!

Deployment

I’m not going to go over all of the instructions on setting up the gcloud command line tool, linking your project, authorizing, etc. It’s well documented here. So, I’m going to assume you made a coffee (or opened a cold beer) and ran through those steps already.

Before you jump in too quickly trying to deploy your function, we need to do one quick thing. We need to tell the gcloud tool to ignore our go.mod and go.sum files as we’re going to use the module vendoring function to connect our modules.

To do this we first create a file called .gcloudignore under the functions directory with the following contents:

go.mod
go.sum

That’s it. It’ll now ignore those files when it tries to deploy our app. Ok, as I mentioned just a moment ago, we also need to vendor our app. To do that, we run:

go mod vendor

This will pull in our common module into our functions module (under a new vendor directory). Go will look in the vendor directory by default when trying to resolve imports, so we should be all good.

We can now deploy our function!

Run:

gcloud functions deploy OutputMessage --runtime go111 --trigger-http

This command deploys our OutputMessage function to the current project as a HTTP function and tells it we want to use the Go 1.11 runtime. It should take 10 — 60seconds for it to deploy (especially if it’s the first time), but after that you will see a bunch of information about the deployment in your console. One of the values printed out will be httpsTrigger. This will be the URL of your new cloud function. Let’s hit that URL.

Open a browser window/tab and enter the httpsTrigger URL with the query string ?message=Hello World appended to the end of your URL. You should see the following JSON output:

{
"data": {
"message": "Hello world"
}
}

If all has gone well you’re now up and running on Google Cloud Functions with Go 1.11!

If you have any issues, try retracing your steps and check out the docs as it’s likely you have missed a configuration step somewhere.

Good luck and have fun writing Functions!

As a quick reminder, all of the code can be found at https://github.com/theyakka/go-func-example.


About Yakka
Yakka is a digital product design and development agency. Whether it’s the web, Flutter, native mobile apps or a back-end project, we’re the ones to get it done for you.

Reach out today!