go-feed
August 8, 2025 ยท View on GitHub
A framework-agnostic Go module for generating RSS and Atom feeds. Inspired by php-feed, this package works seamlessly with any Go web framework including Gin, Echo, Fiber, Chi, and standard net/http.
Features
- Framework-agnostic: Use with Gin, Echo, Fiber, Chi, or standard net/http (adapters available separately)
- Multiple formats: RSS 2.0 and Atom 1.0 support
- Rich content: Support for images, enclosures, categories, and custom elements
- Modern Go: Type-safe, extensible, and robust (Go 1.22+)
- High test coverage: Comprehensive test suite with CI/CD integration
- Easy integration: Simple API, drop-in for handlers/middleware
- Extensible: Adapters for popular Go web frameworks
- Production ready: Used in production environments
Quick Links
- ๐ Installation
- ๐ Usage Examples
- ๐ง Framework Adapters
- ๏ฟฝ Working Examples
- ๐ Documentation Wiki
- ๐งช Testing & Development
- ๐ค Contributing
- ๐ Security Policy
- ๐ Support & Funding
- ๐ License
Installation
Core Library
go get go.rumenx.com/feed
Framework Adapters (Optional)
Each framework adapter is a separate module. Install only what you need:
# For Gin
go get go.rumenx.com/feed/adapters/gin
# For Echo
go get go.rumenx.com/feed/adapters/echo
# For Fiber
go get go.rumenx.com/feed/adapters/fiber
# For Chi
go get go.rumenx.com/feed/adapters/chi
Usage
Basic Example (net/http)
package main
import (
"net/http"
"time"
"go.rumenx.com/feed"
)
func feedHandler(w http.ResponseWriter, r *http.Request) {
f := feed.New()
// Set feed metadata
f.SetTitle("My Blog Feed")
f.SetDescription("Latest posts from my blog")
f.SetLink("https://example.com")
f.SetLanguage("en-us")
// Add feed items
f.AddItem(feed.Item{
Title: "First Post",
Description: "This is my first blog post",
Link: "https://example.com/posts/first-post",
Author: "Rumen Damyanov",
PubDate: time.Now(),
GUID: "https://example.com/posts/first-post",
})
// Render as RSS
w.Header().Set("Content-Type", "application/xml")
rss, err := f.RSS()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(rss)
}
func main() {
http.HandleFunc("/feed.xml", feedHandler)
http.ListenAndServe(":8080", nil)
}
Advanced Features
f := feed.New()
// Set comprehensive feed metadata
f.SetTitle("My News Site")
f.SetDescription("Latest news and updates")
f.SetLink("https://example.com")
f.SetLanguage("en-us")
f.SetCopyright("ยฉ 2025 Example News")
f.SetManagingEditor("editor@example.com (News Editor)")
f.SetWebmaster("webmaster@example.com (Web Master)")
f.SetTTL(60) // Cache for 60 minutes
// Add item with rich content
f.AddItem(feed.Item{
Title: "Breaking News",
Description: "Important news update with media",
Link: "https://example.com/news/breaking",
Author: "reporter@example.com (News Reporter)",
PubDate: time.Now(),
GUID: "https://example.com/news/breaking",
Categories: []string{"news", "breaking", "politics"},
Enclosure: &feed.Enclosure{
URL: "https://example.com/audio/news.mp3",
Length: "1048576",
Type: "audio/mpeg",
},
Images: []feed.Image{
{
URL: "https://example.com/images/news.jpg",
Title: "Breaking News Image",
Link: "https://example.com/news/breaking",
},
},
})
// Multiple output formats
rssData, _ := f.RSS() // RSS 2.0
atomData, _ := f.Atom() // Atom 1.0
Framework Adapters
Framework adapters are separate modules to keep the core library dependency-free. Install only the adapters you need.
Gin Example
package main
import (
"github.com/gin-gonic/gin"
"go.rumenx.com/feed/adapters/gin"
)
func main() {
r := gin.Default()
r.GET("/feed.xml", ginadapter.Feed(func() *feed.Feed {
f := feed.New()
f.SetTitle("My Site")
f.AddItem(feed.Item{
Title: "Hello World",
Link: "https://example.com/hello",
})
return f
}))
r.Run(":8080")
}
Fiber Example
package main
import (
"github.com/gofiber/fiber/v2"
"go.rumenx.com/feed/adapters/fiber"
)
func main() {
app := fiber.New()
app.Get("/feed.xml", fiberadapter.Feed(func() *feed.Feed {
f := feed.New()
f.SetTitle("My Site")
f.AddItem(feed.Item{
Title: "Hello World",
Link: "https://example.com/hello",
})
return f
}))
app.Listen(":8080")
}
Echo Example
package main
import (
"github.com/labstack/echo/v4"
"go.rumenx.com/feed/adapters/echo"
)
func main() {
e := echo.New()
e.GET("/feed.xml", echoadapter.Feed(func() *feed.Feed {
f := feed.New()
f.SetTitle("My Site")
f.AddItem(feed.Item{
Title: "Hello World",
Link: "https://example.com/hello",
})
return f
}))
e.Start(":8080")
}
Chi Example
package main
import (
"net/http"
"github.com/go-chi/chi/v5"
"go.rumenx.com/feed/adapters/chi"
)
func main() {
r := chi.NewRouter()
r.Get("/feed.xml", chiadapter.Feed(func() *feed.Feed {
f := feed.New()
f.SetTitle("My Site")
f.AddItem(feed.Item{
Title: "Hello World",
Link: "https://example.com/hello",
})
return f
}))
http.ListenAndServe(":8080", r)
}
Multiple Methods for Adding Items
Add() vs AddItem()
You can add feed items using either the Add() or AddItem() methods:
Add() โ Simple, parameter-based:
// Recommended for simple use cases
f.Add(
"Hello World", // title
"This is a hello world post", // description
"https://example.com/hello", // link
"author@example.com", // author
time.Now(), // pubDate
)
AddItem() โ Advanced, struct-based:
// Add a single item with a struct
f.AddItem(feed.Item{
Title: "Hello World",
Description: "This is a hello world post",
Link: "https://example.com/hello",
Author: "author@example.com",
PubDate: time.Now(),
Categories: []string{"general", "blog"},
})
// Add multiple items at once (batch add)
f.AddItems([]feed.Item{
{Title: "Post 1", Link: "https://example.com/post1"},
{Title: "Post 2", Link: "https://example.com/post2"},
})
Working Examples
The examples/ directory contains complete, runnable applications:
Framework Examples
Located in examples/frameworks/, each with its own module:
| Framework | Port | Run Command | Features |
|---|---|---|---|
| Gin | :8080 | cd examples/frameworks/gin && go run main.go | Clean API, middleware support |
| Echo | :8081 | cd examples/frameworks/echo && go run main.go | Performance-focused, middleware ecosystem |
| Fiber | :8082 | cd examples/frameworks/fiber && go run main.go | Express-inspired, fast HTTP engine |
| Chi | :8083 | cd examples/frameworks/chi && go run main.go | Lightweight router, auto-detection middleware |
Basic Examples
examples/basic/- Simple RSS/Atom generationexamples/complete/- Advanced features demonstration
Each example includes:
- ๐ก RSS 2.0 feeds (
/feed.xml) - โ๏ธ Atom 1.0 feeds (
/atom.xml) - ๐ Multi-format endpoints (
/feed?format=rss|atom) - ๐ Interactive HTML browsers
- ๐ฏ Framework-specific features
Documentation
For comprehensive documentation and examples:
- ๐ Quick Start Guide - Get up and running quickly
- ๐ง Basic Usage - Core functionality and examples
- ๐ Advanced Usage - Advanced features and customization
- ๐ Framework Integration - Integration with popular frameworks
- ๐ฏ Best Practices - Performance tips and recommendations
- ๐ค Contributing Guidelines - How to contribute to this project
- ๐ Security Policy - Security guidelines and vulnerability reporting
- ๐ Funding & Support - Support and sponsorship information
Testing & Development
Running Tests
# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Generate HTML coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
Code Quality
# Run static analysis
go vet ./...
# Format code
go fmt ./...
# Run linter (if installed)
golangci-lint run
Contributing
We welcome contributions! Please see our Contributing Guidelines for details on:
- Development setup
- Coding standards
- Testing requirements
- Pull request process
Security
If you discover a security vulnerability, please review our Security Policy for responsible disclosure guidelines.
Support
If you find this package helpful, consider:
- โญ Starring the repository
- ๐ Supporting development
- ๐ Reporting issues
- ๐ค Contributing improvements