Groundfloor Docs
Language runtimes

Go

Write a Coderunner Function, Job or Schedule in Go.

Use this reference for Functions, Jobs and Schedules written in Go. For a container with your own web server, see Services.

Project files

my-function/
├── handler.go
├── go.mod
└── helpers.go      (optional)

Zip these at the root of the archive, not inside a folder. Every .go file uses package main, and helper files sit next to handler.go rather than in subfolders.

go.mod
module app

go 1.24

The handler

Export a function named Handler that returns a HandlerResult:

handler.go
package main

type HandlerResult struct {
	StatusCode int                    `json:"-"`
	Headers    map[string]string      `json:"headers"`
	Body       map[string]interface{} `json:"body"`
}

func Handler(context map[string]interface{}, payload map[string]interface{}) HandlerResult {
	// your code
}
  • payload is the JSON input: the request body for a Function, the run's input for a Job.
  • context is reserved for information from the runtime. Don't rely on its contents yet.

You don't need http.ListenAndServe or any routing.

Function example

handler.go
package main

import (
	"fmt"
	"net/http"
)

type HandlerResult struct {
	StatusCode int                    `json:"-"`
	Headers    map[string]string      `json:"headers"`
	Body       map[string]interface{} `json:"body"`
}

func Handler(context map[string]interface{}, payload map[string]interface{}) HandlerResult {
	headers := map[string]string{"content-type": "application/json"}
	name, _ := payload["name"].(string)
	if name == "" {
		return HandlerResult{
			StatusCode: http.StatusBadRequest,
			Headers:    headers,
			Body:       map[string]interface{}{"error": "name is required"},
		}
	}
	return HandlerResult{
		StatusCode: http.StatusOK,
		Headers:    headers,
		Body:       map[string]interface{}{"greeting": fmt.Sprintf("Hello, %s", name)},
	}
}

Return an error result rather than panicking.

Job and Schedule example

handler.go
func Handler(context map[string]interface{}, payload map[string]interface{}) HandlerResult {
	log.Println("Import started")
	count, err := importCustomers(payload)
	if err != nil {
		log.Println("Import failed:", err)
		return HandlerResult{StatusCode: http.StatusInternalServerError, Body: map[string]interface{}{"error": "import failed"}}
	}
	log.Printf("Imported %d customers\n", count)
	return HandlerResult{StatusCode: http.StatusOK, Body: map[string]interface{}{"imported": count}}
}

Error handling is up to you; see Jobs.

Settings, secrets and logs

Deploy

gf deploy --name my-function --runtime go --workload-type function

Or create the Coderunner in the Client Portal and upload the ZIP; see Functions.

On this page