Building a minimal Go framework in public (v0.1.3)
Source: Dev.to
Introduction
Most Go web frameworks pull in dozens of dependencies—Gin has 9 direct dependencies, Echo 11, Fiber 15—so your go.mod quickly looks like a phone book. Marten takes a different approach: it uses only what Go gives you (e.g., net/http, encoding/json). No external packages, no vendor lock‑in.
Complete API Example
package main
import (
"github.com/gomarten/marten"
"github.com/gomarten/marten/middleware"
)
func main() {
app := marten.New()
app.Use(middleware.Logger)
app.Use(middleware.Recover)
app.GET("/", func(c *marten.Ctx) error {
return c.OK(marten.M{"message": "Hello, World!"})
})
app.GET("/users/:id", func(c *marten.Ctx) error {
id := c.ParamInt("id")
return c.OK(marten.M{"id": id})
})
app.Run(":8080")
}
Router
Marten uses a radix‑tree router for efficient path matching. It supports:
- Path parameters (
:id) - Wildcards (
*filepath) - Route groups
api := app.Group("/api/v1")
api.GET("/users", listUsers)
api.GET("/users/:id", getUser)
api.POST("/users", createUser)
Middleware
Middleware in Marten is just a function that wraps a handler:
func Timer(next marten.Handler) marten.Handler {
return func(c *marten.Ctx) error {
start := time.Now()
err := next(c)
log.Printf("took %v", time.Since(start))
return err
}
}
Built‑in Middleware
Marten ships with 14 built‑in middleware components:
LoggerRecoverCORSRateLimitBasicAuthTimeoutSecureBodyLimitCompressETagRequestIDStaticNoCache
Context (Ctx) Usage
Every request gets a Ctx object from a sync.Pool, reducing allocations and keeping memory usage low:
func handler(c *marten.Ctx) error {
// Path parameters
id := c.Param("id")
// Query parameters
page := c.QueryInt("page")
// JSON binding
var user User
c.Bind(&user)
// Response helpers
return c.OK(user)
}
Static File Serving (v0.1.3)
The latest release adds static file serving with a full feature set:
app.Use(middleware.StaticWithConfig(middleware.StaticConfig{
Root: "./public",
Prefix: "/static",
MaxAge: 3600,
Browse: false,
}))
Features include content‑type detection, HTTP caching (If-Modified-Since), directory browsing, and protection against directory‑traversal attacks.
Performance Benchmarks
Benchmarks against Gin, Echo, and Chi show Marten holding its own:
| Benchmark | Marten | Gin | Echo | Chi |
|---|---|---|---|---|
| Static Route | 1464 ns/op | 1336 ns/op | 1436 ns/op | 2202 ns/op |
| Param Route | 1564 ns/op | 1418 ns/op | 1472 ns/op | 2559 ns/op |
| JSON Response | 1755 ns/op | 2050 ns/op | 1835 ns/op | 1868 ns/op |
Not the fastest, but competitive—and with zero dependencies.
Building Production‑Ready APIs
app := marten.New()
app.Use(
middleware.RequestID,
middleware.Logger,
middleware.Recover,
middleware.CORS(middleware.DefaultCORSConfig()),
middleware.RateLimit(middleware.RateLimitConfig{
Max: 100,
Window: time.Minute,
}),
)
api := app.Group("/api/v1")
api.GET("/users", listUsers)
api.POST("/users", createUser, authMiddleware)
SPA Fallback
// API routes
app.GET("/api/users", listUsers)
// Serve static files
app.Use(middleware.Static("./dist"))
// SPA fallback
app.NotFound(func(c *marten.Ctx) error {
if strings.HasPrefix(c.Path(), "/api/") {
return c.NotFound("endpoint not found")
}
// Serve index.html for client‑side routing
return c.HTML(200, indexHTML)
})
Tests
Marten v0.1.3 ships with 325 tests covering:
- Unit tests for every component
- Integration tests for real‑world workflows
- Stress tests with 1,000+ concurrent requests
- Edge cases and error conditions
All tests pass with Go’s race detector; no known memory leaks.
What Marten Doesn’t Provide
- ORM integration – use
database/sqldirectly - Template engine – use
html/templatefrom the stdlib - Validation library – write your own or import a third‑party package
- WebSocket support – planned for a future release
Philosophy
If the standard library can do it, use the standard library. If you need more, add it yourself—still keeping the zero‑dependency constraint.
Future Releases
- WebSocket middleware
- Template rendering helpers
- Session management middleware
- Enhanced static file serving options
All with the same zero‑dependency philosophy.
Installation
go get github.com/gomarten/marten@v0.1.3
Check out the examples for CRUD APIs, JWT auth, file servers, and more.
Conclusion
Marten isn’t trying to replace Gin or Echo; it’s an experiment in minimalism—a proof that you can build a capable web framework without pulling in the world. Sometimes, less is more.
Links
- GitHub:
- Documentation:
- Discussions: