Build functions with Go

Netlify can automatically detect and build your Go serverless functions from source. To add a function, create a dedicated function subdirectory in your configured functions directory. Then, add your Go file to that subdirectory. The function endpoint is determined by the name of its dedicated parent directory.

For example, with a configured functions directory of my_functions and a target function endpoint name of hello, you could save the function file in one of the following ways:

  • my_functions/hello/hello.go
  • my_functions/hello/main.go

Either of the above formats would deploy a synchronous function that can be called on the following endpoint, relative to the base URL of your site: /.netlify/functions/hello.

For a background function, the subdirectory that contains the background function file must end with -background, or the function file name must end with -background.

With an example configured functions directory of my_functions and a target function endpoint name of hello-background, you could save a background function file in either of these ways:

  • my_functions/hello-background/hello-background.go
  • my_functions/hello-background/main.go

These formats would deploy a background function that can be called on the following endpoint, relative to the base URL of your site: /.netlify/functions/hello-background.

Reserved names for event-driven functions

Certain function names are reserved as triggers initiated by various built-in events on your Netlify site. You can find a list of these function names and how they work on the page about event-driven functions.

If you don’t want to use Netlify’s auto-detect and auto-build for Go functions, you can use a custom build command or precompile the binaries yourself.

# Synchronous function format

This section walks you through the format of a synchronous function that Netlify can deploy and serve with a dedicated endpoint.

Each Go file to be deployed as a function must include a handler function to receive invocation events:

func handler(ctx context.Context, request events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) {
  # Your server-side functionality
}

The ctx parameter includes information about the context in which the function was called, like certain Identity user information, for example.

The response must be compatible with the Amazon API Gateway response:

return &events.APIGatewayProxyResponse{
	StatusCode: 200,
	Body:       "Hello, World",
}, nil

Here’s a complete example function hello.go:

package main

import (
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
	"net/http"
)

func handler(request events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) {
	return &events.APIGatewayProxyResponse{
		StatusCode:        200,
		Headers:           map[string]string{"Content-Type": "text/plain"},
		MultiValueHeaders: http.Header{"Set-Cookie": {"Ding", "Ping"}},
		Body:              "Hello, World!",
		IsBase64Encoded:   false,
	}, nil
}

func main() {
	// Make the handler available for Remote Procedure Call
	lambda.Start(handler)
}

This function would be called from your site at /.netlify/functions/hello, and on success, would return the 200 status code and the string, “Hello, World”.

For more examples to help you learn how to create functions with Go, visit the AWS Lambda for Go repository.

# Access the ClientContext

Netlify can add extra request information to a function call using a ClientContext parameter. To access this information, you need to use a handler definition that includes a Go Context struct. This object can be transformed into a LambdaContext to access the ClientContext data:

package main

import (
	"context"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-lambda-go/lambdacontext"
)

func handler(ctx context.Context, request events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) {
	lc, ok := lambdacontext.FromContext(ctx)
	if !ok {
		return &events.APIGatewayProxyResponse{
			StatusCode: 503,
			Body:       "Something went wrong :(",
		}, nil
	}

	cc := lc.ClientContext

	return &events.APIGatewayProxyResponse{
		StatusCode: 200,
		Body:       "Hello, " + cc.Client.AppTitle,
	}, nil
}

func main() {
	lambda.Start(handler)
}

# Background function format

This feature is in BETA and may not be available on all plans.

Background function syntax is similar to synchronous function syntax, but you will generally pass the function result to a destination other than the originating client. Like the synchronous function format, a Go file to be deployed as a background function must include a handler function to receive invocation events. Netlify provides information about the context in which the function was called using the ctx parameter.

Here’s a simplified example background function that you can use to test that your function runs longer than 10 seconds, count-background.go:

package main

import (
	"context"
	"log"
	"time"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

func handler(ctx context.Context, request events.APIGatewayProxyRequest) (*events.APIGatewayProxyResponse, error) {
	for i := 0; i < 60; i++ {
		log.Println(i)
		time.Sleep(1 * time.Second)
	}
	return nil, nil
}

func main() {
	lambda.Start(handler)
}

This function would be called from your site at /.netlify/functions/count-background. When invoked, the function returns an initial 202 success response. When successfully executed, the function logs numbers 1 through 60.

For an extended example that demonstrates a more likely background function use case, this save.go function compiles to identity-signup-background. This example doesn’t use Netlify’s auto-detect and auto-build. Instead, it uses a custom build command.

This event-triggered background function is called on a new user email and password signup. When the function is executed, it finds and downloads a user’s Gravatar profile image, resizes the image to three different sizes, and saves these images to the site’s repository. For more details, visit the example’s repository README.

# Custom build command

If you want more control over go build during your site’s build, you can include it in your build command or invoke it through a file called by the build command.

# Build settings and dependency management

The Go version used in the deployment pipeline is determined by your site’s selected build image.

Before building your Go source with a build command, Netlify needs to know the expected Go import path for your project. Use the GO_IMPORT_PATH environment variable to set the right import path. You can do this in the Netlify UI at Site settings > Build & deploy > Environment > Environment variables, or in your netlify.toml file. The path value should point to your source repository on your Git provider, for example github.com/netlify/go-functions-example.

Once the Go import path is set, go get will work as expected, and you can also use any dependency management tool to download dependencies for your project.

Compiled binaries must be added to your configured functions directory.

You can access a full example in the netlify/go-functions-example repository.

# Precompiled binaries

If you already have precompiled binaries for your Go functions, Netlify can deploy them as functions. Precompiled binaries must be added to your configured functions directory before you begin building your site.

# Tools

You can use Netlify Dev to help with writing, testing, and deploying your Go functions on Netlify. Netlify CLI includes tools for local function development and streamlined deployment through a simulated Netlify production environment. The netlify dev command starts a framework server if a framework is detected and handles redirects, proxy rules, Netlify Functions, and add-ons.