Building Azure Functions in Go

I’ve been exploring how to run Azure Functions in Go using the Custom Handler pattern. No special SDK, no code generation — just standard Go with net/http.

Here’s how it works.

Contents:

Why This Approach

Azure Functions has built-in support for languages like C#, JavaScript, Python, and Java. For Go, the recommended approach is Custom Handlers — the host starts your HTTP server and forwards requests.

Why this works well:

  • No SDK required — Use standard net/http, the same code runs anywhere
  • Simple architecture — Just an HTTP server, nothing special
  • Easy debugging — Test locally with go run or any HTTP client
  • Production ready — Custom Handlers are a documented, stable feature
  • Portable — Your code isn’t tied to Azure, it’s just a Go web server

The Architecture

The Azure Functions Host starts your Go binary and forwards HTTP requests:

Internet → Azure Functions Host → Your Go Binary (net/http server)

Your binary reads the port from an environment variable and serves requests (main.go):

func main() {
    port := os.Getenv("FUNCTIONS_CUSTOMHANDLER_PORT")
    if port == "" {
        port = "8080"
    }

    http.HandleFunc("/api/hello", helloHandler)
    http.HandleFunc("/api/health", healthHandler)

    log.Printf("Starting server on port %s", port)
    log.Fatal(http.ListenAndServe(":"+port, nil))
}

The host.json tells Azure Functions to use your binary as a Custom Handler:

{
  "version": "2.0",
  "customHandler": {
    "description": {
      "defaultExecutablePath": "handler"
    },
    "enableForwardingHttpRequest": true
  }
}

With enableForwardingHttpRequest: true, the host passes through HTTP requests directly — your Go code sees standard http.Request and http.ResponseWriter.

Writing a Function

A simple hello function:

func helloHandler(w http.ResponseWriter, r *http.Request) {
    name := r.URL.Query().Get("name")
    if name == "" {
        name = "World"
    }

    response := map[string]string{
        "message": fmt.Sprintf("Hello, %s!", name),
    }

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(response)
}

Each function needs a function.json that defines its trigger:

{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"],
      "route": "hello"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
  ]
}

That’s it. Standard Go HTTP handlers, standard JSON responses.

The QR Generator Sample

The repo includes a complete QR code generator with a web UI (main.go):

func handleGenerate(w http.ResponseWriter, r *http.Request) {
    if r.Method == http.MethodGet {
        // Serve the web UI
        w.Header().Set("Content-Type", "text/html")
        fmt.Fprint(w, landingPageHTML)
        return
    }

    // POST: Generate QR code
    var req GenerateRequest
    json.NewDecoder(r.Body).Decode(&req)

    png, _ := qrcode.Encode(req.Content, qrcode.Medium, req.Size)

    json.NewEncoder(w).Encode(GenerateResponse{
        Image:   base64.StdEncoding.EncodeToString(png),
        Content: req.Content,
        Size:    req.Size,
    })
}

The web UI lets users enter text and see the generated QR code:

  • GET /generate — Interactive web page
  • POST /generate — API returns base64-encoded PNG
  • GET /health — Health check endpoint

Deploying to Azure

Each sample includes deployment scripts (deploy.sh, deploy.ps1). For the QR generator:

cd samples/qr-generator

# Deploy to Azure (creates everything: resource group, storage, function app)
./deploy.sh -g my-resource-group -l westus2

# Or on Windows
.\deploy.ps1 -ResourceGroupName my-resource-group -Location westus2

The script:

  1. Cross-compiles to Linux (GOOS=linux GOARCH=amd64)
  2. Creates Azure resources (resource group, storage account, function app)
  3. Deploys with func azure functionapp publish

For local development:

# Build
go build -o handler .

# Run with Azure Functions Core Tools
func start

Try It

Clone the repo and try the samples:

git clone https://github.com/laveeshb/azure-functions-go-worker.git
cd azure-functions-go-worker

# Hello World - basic HTTP function
cd samples/hello-world/src
go build -o handler .
func start

# QR Generator - web UI + API
cd samples/qr-generator
go build -o handler .
func start

The code is on GitHub.

Comments