Controllers
Controllers organize your request handling logic into structs with action methods. Instead of defining inline handler functions for every route, you group related actions into a controller โ following Laravel-style organization.
What Is a Controller?
A controller is a Go struct whose methods match the Nimbus handler signature: func(*http.Context) error. Each method represents one action (listing resources, showing a single resource, creating, updating, or deleting).
Creating a Controller
Create a file in app/controllers/. Define a struct and attach action methods:
package controllers
import (
"github.com/CodeSyncr/nimbus/http"
)
type PostsController struct{}
func (pc *PostsController) Index(c *http.Context) error {
posts := []map[string]string{
{"id": "1", "title": "Hello World"},
{"id": "2", "title": "Getting Started with Nimbus"},
}
return c.JSON(http.StatusOK, posts)
}
func (pc *PostsController) Show(c *http.Context) error {
id := c.Param("id")
return c.JSON(http.StatusOK, map[string]string{"id": id})
}
func (pc *PostsController) Create(c *http.Context) error {
return c.JSON(http.StatusCreated, map[string]string{"message": "created"})
}
func (pc *PostsController) Update(c *http.Context) error {
id := c.Param("id")
return c.JSON(http.StatusOK, map[string]string{"id": id, "updated": "true"})
}
func (pc *PostsController) Delete(c *http.Context) error {
id := c.Param("id")
return c.JSON(http.StatusOK, map[string]string{"id": id, "deleted": "true"})
}
Registering Controller Routes
In main.go, instantiate the controller and bind each action to a route:
posts := &controllers.PostsController{}
app.Router.Get("/posts", posts.Index)
app.Router.Get("/posts/:id", posts.Show)
app.Router.Post("/posts", posts.Create)
app.Router.Put("/posts/:id", posts.Update)
app.Router.Delete("/posts/:id", posts.Delete)
Resourceful Routing Pattern
The pattern above follows RESTful conventions. Here is the full mapping for a resource:
GET /postsโIndexโ list all postsGET /posts/:idโShowโ show one postPOST /postsโCreateโ create a new postPUT /posts/:idโUpdateโ replace a postDELETE /posts/:idโDeleteโ remove a post
Using Route Groups
Group controller routes under a shared prefix:
api := app.Router.Group("/api")
posts := &controllers.PostsController{}
api.Get("/posts", posts.Index)
api.Get("/posts/:id", posts.Show)
api.Post("/posts", posts.Create)
api.Put("/posts/:id", posts.Update)
api.Delete("/posts/:id", posts.Delete)
Passing Data to Views
Controllers can render .nimbus templates by calling c.View() with a data map:
func (pc *PostsController) Index(c *http.Context) error {
posts := fetchPostsFromDB()
return c.View("posts/index", map[string]any{
"title": "All Posts",
"posts": posts,
})
}
The keys in the map become available as variables in your template. For example, title and posts can be referenced in the posts/index.nimbus view file.
Controller with Dependencies
Add fields to the controller struct for dependencies like a database connection:
type UsersController struct {
DB *gorm.DB
}
func (uc *UsersController) Index(c *http.Context) error {
var users []User
uc.DB.Find(&users)
return c.JSON(http.StatusOK, users)
}
// In main.go
users := &controllers.UsersController{DB: db}
app.Router.Get("/users", users.Index)