Appearance
Go Examples
Generate OG images using Go.
Basic Generation
go
package main
import (
"bytes"
"encoding/json"
"io"
"net/http"
"os"
)
type OGImageRequest struct {
Title string `json:"title"`
Subtitle string `json:"subtitle,omitempty"`
Template string `json:"template,omitempty"`
Theme string `json:"theme,omitempty"`
}
func generateOGImage(params OGImageRequest) ([]byte, error) {
apiKey := os.Getenv("OG_IMAGE_API_KEY")
jsonData, err := json.Marshal(params)
if err != nil {
return nil, err
}
req, err := http.NewRequest("POST", "https://ogimageapi.io/api/generate", bytes.NewBuffer(jsonData))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", apiKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
func main() {
imageData, err := generateOGImage(OGImageRequest{
Title: "Hello from Go!",
Subtitle: "Generated with OG Image API",
Template: "default",
Theme: "dark",
})
if err != nil {
panic(err)
}
os.WriteFile("og-image.png", imageData, 0644)
}HTTP Handler
go
package main
import (
"bytes"
"encoding/json"
"io"
"net/http"
"os"
)
func ogImageHandler(w http.ResponseWriter, r *http.Request) {
title := r.URL.Query().Get("title")
if title == "" {
title = "Default Title"
}
subtitle := r.URL.Query().Get("subtitle")
params := map[string]string{
"title": title,
"subtitle": subtitle,
"template": "default",
"theme": "dark",
}
jsonData, _ := json.Marshal(params)
req, _ := http.NewRequest("POST", "https://ogimageapi.io/api/generate", bytes.NewBuffer(jsonData))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", os.Getenv("OG_IMAGE_API_KEY"))
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
http.Error(w, "Failed to generate image", http.StatusInternalServerError)
return
}
defer resp.Body.Close()
imageData, _ := io.ReadAll(resp.Body)
w.Header().Set("Content-Type", "image/png")
w.Header().Set("Cache-Control", "public, max-age=86400")
w.Write(imageData)
}
func main() {
http.HandleFunc("/og", ogImageHandler)
http.ListenAndServe(":8080", nil)
}With Gin Framework
go
package main
import (
"bytes"
"encoding/json"
"io"
"net/http"
"os"
"github.com/gin-gonic/gin"
)
type OGService struct {
apiKey string
client *http.Client
}
func NewOGService() *OGService {
return &OGService{
apiKey: os.Getenv("OG_IMAGE_API_KEY"),
client: &http.Client{},
}
}
func (s *OGService) Generate(params map[string]interface{}) ([]byte, error) {
jsonData, _ := json.Marshal(params)
req, _ := http.NewRequest("POST", "https://ogimageapi.io/api/generate", bytes.NewBuffer(jsonData))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", s.apiKey)
resp, err := s.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
func main() {
r := gin.Default()
ogService := NewOGService()
r.GET("/og", func(c *gin.Context) {
title := c.DefaultQuery("title", "Default Title")
subtitle := c.Query("subtitle")
imageData, err := ogService.Generate(map[string]interface{}{
"title": title,
"subtitle": subtitle,
"template": "default",
"theme": "dark",
})
if err != nil {
c.String(http.StatusInternalServerError, "Failed to generate")
return
}
c.Header("Content-Type", "image/png")
c.Header("Cache-Control", "public, max-age=86400")
c.Data(http.StatusOK, "image/png", imageData)
})
r.Run(":8080")
}Concurrent Batch Generation
go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"sync"
)
type Post struct {
Slug string
Title string
Excerpt string
}
func generateForPost(post Post, wg *sync.WaitGroup, results chan<- error) {
defer wg.Done()
params := map[string]string{
"title": post.Title,
"subtitle": post.Excerpt,
"template": "blog",
"theme": "dark",
}
jsonData, _ := json.Marshal(params)
req, _ := http.NewRequest("POST", "https://ogimageapi.io/api/generate", bytes.NewBuffer(jsonData))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", os.Getenv("OG_IMAGE_API_KEY"))
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
results <- fmt.Errorf("failed for %s: %w", post.Slug, err)
return
}
defer resp.Body.Close()
imageData, _ := io.ReadAll(resp.Body)
err = os.WriteFile(fmt.Sprintf("./og/%s.png", post.Slug), imageData, 0644)
if err != nil {
results <- fmt.Errorf("failed to save %s: %w", post.Slug, err)
return
}
results <- nil
}
func main() {
posts := []Post{
{Slug: "post-1", Title: "First Post", Excerpt: "Introduction"},
{Slug: "post-2", Title: "Second Post", Excerpt: "More content"},
{Slug: "post-3", Title: "Third Post", Excerpt: "Even more"},
}
os.MkdirAll("./og", 0755)
var wg sync.WaitGroup
results := make(chan error, len(posts))
for _, post := range posts {
wg.Add(1)
go generateForPost(post, &wg, results)
}
wg.Wait()
close(results)
for err := range results {
if err != nil {
fmt.Println("Error:", err)
}
}
fmt.Println("Done!")
}Error Handling
go
func generateWithRetry(params map[string]interface{}, maxRetries int) ([]byte, error) {
var lastErr error
for i := 0; i < maxRetries; i++ {
imageData, err := generateOGImage(params)
if err == nil {
return imageData, nil
}
lastErr = err
// Exponential backoff
time.Sleep(time.Duration(math.Pow(2, float64(i))) * time.Second)
}
return nil, fmt.Errorf("failed after %d retries: %w", maxRetries, lastErr)
}