Back to Blog
Implementation5 min readApril 21, 2026

Webhook Receiver in Go: Production Guide

Go's standard library has everything you need for a webhook receiver: net/http, crypto/hmac, crypto/sha256. Here's the complete implementation with signature verification and async processing.

W
WebhookWhisper Team
April 21, 2026

Go's standard library provides everything you need to build a fast, correct webhook receiver — no external dependencies required.

Complete Implementation

package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"io"
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
)

var (
	webhookSecret = os.Getenv("WEBHOOK_SECRET")
	processed     = &sync.Map{}
)

func verifySignature(body []byte, sigHeader string) bool {
	mac := hmac.New(sha256.New, []byte(webhookSecret))
	mac.Write(body)
	expected := hex.EncodeToString(mac.Sum(nil))
	provided := strings.TrimPrefix(sigHeader, "sha256=")
	return hmac.Equal([]byte(expected), []byte(provided))
}

func webhookHandler(w http.ResponseWriter, r *http.Request) {
	body, err := io.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "read error", http.StatusBadRequest)
		return
	}
	defer r.Body.Close()

	sig := r.Header.Get("X-Hub-Signature-256")
	if sig == "" || !verifySignature(body, sig) {
		http.Error(w, "invalid signature", http.StatusUnauthorized)
		return
	}

	eventID := r.Header.Get("X-GitHub-Delivery")

	w.WriteHeader(http.StatusOK)
	w.Write([]byte(`{"ok":true}`))

	go func() {
		if _, loaded := processed.LoadOrStore(eventID, true); loaded {
			return
		}
		var event map[string]interface{}
		if err := json.Unmarshal(body, &event); err != nil {
			return
		}
		log.Printf("Processing %s: action=%v", eventID, event["action"])
	}()
}

func main() {
	http.HandleFunc("/webhooks/github", webhookHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

Why Go Excels for Webhook Receivers

  • Goroutines: trivial async processing — spin up a goroutine after returning 200
  • sync.Map: concurrent-safe idempotency store
  • io.ReadAll: gives you raw bytes before parsing
  • Low memory: handles thousands of concurrent connections

Use WebhookWhisper to forward live webhooks to your local Go server during development.

#go#golang#webhooks#implementation

Ready to test your webhooks?

Get a free HTTPS endpoint in under 5 seconds — no signup required.

Create Free Account
Webhook Receiver Go: Complete Implementation Guide (2026) | WebhookWhisper