Build functions with Go

Netlify can automatically detect and build your Go serverless functions from source. To add a function, create a Go file in a dedicated function subdirectory in your functions directory. The default functions directory is YOUR_BASE_DIRECTORY/netlify/functions. Netlify will access the functions directory during every build, preparing and deploying each supported code file as a function.

You must store your function in a subdirectory dedicated to the function. The function endpoint is determined by the name of its dedicated parent directory.

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

  • netlify/functions/hello.go
  • netlify/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 target function endpoint name of hello-background, you could save a background function file in either of these ways:

  • netlify/functions/hello-background/hello-background.go
  • netlify/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.

# Environment variables

You can access Netlify build environment variables to inject their values into your function files before your functions are deployed. A common use case is modifying function behavior depending on deploy context, for example fetching data from a staging vs. production third-party API endpoint.

You can also create deploy environment variables on Netlify and access their values in your functions at execution time. A common use case is injecting information you don’t want to store in your repository such as API keys. Because Netlify Functions are powered by AWS Lambda, AWS’s environment property limits apply to deploy environment variables used with Netlify Functions.

# Tools

You can use Netlify Dev to help with writing and testing your Go functions on Netlify. Netlify CLI includes tools for local function development 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.

Deploy functions: Custom build

Deploy functions: External build