go-chi-router
8
总安装量
8
周安装量
#34453
全站排名
安装命令
npx skills add https://github.com/cristiano-pacheco/ai-tools --skill go-chi-router
Agent 安装分布
gemini-cli
8
claude-code
8
github-copilot
8
codex
8
amp
8
kimi-cli
8
Skill 文档
Go Chi Router
Generate Chi router implementations for Go backend HTTP transport layer.
Location: internal/modules/<module>/http/chi/router/<resource>_router.go
Router Implementation
package router
import (
"github.com/cristiano-pacheco/bricks/pkg/http/server/chi"
"github.com/cristiano-pacheco/pingo/internal/modules/<module>/http/chi/handler"
)
type ResourceRouter struct {
handler *handler.ResourceHandler
}
func NewResourceRouter(h *handler.ResourceHandler) *ResourceRouter {
return &ResourceRouter{handler: h}
}
func (r *ResourceRouter) Setup(server *chi.Server) {
router := server.Router()
router.Get("/api/v1/resources", r.handler.ListResources)
router.Get("/api/v1/resources/{id}", r.handler.GetResource)
router.Post("/api/v1/resources", r.handler.CreateResource)
router.Put("/api/v1/resources/{id}", r.handler.UpdateResource)
router.Delete("/api/v1/resources/{id}", r.handler.DeleteResource)
}
Router Patterns
Custom Endpoints
Use POST with a verb suffix for non-CRUD state transitions. Use nested paths for sub-resources.
func (r *ResourceRouter) Setup(server *chi.Server) {
router := server.Router()
router.Get("/api/v1/resources", r.handler.ListResources)
router.Post("/api/v1/resources", r.handler.CreateResource)
router.Post("/api/v1/resources/{id}/activate", r.handler.ActivateResource)
router.Post("/api/v1/resources/{id}/deactivate", r.handler.DeactivateResource)
router.Get("/api/v1/resources/{id}/items", r.handler.ListResourceItems)
router.Post("/api/v1/resources/{id}/items", r.handler.AddResourceItem)
}
Route Groups (with middleware)
Use router.Group to scope middleware to a subset of routes without affecting others.
func (r *ResourceRouter) Setup(server *chi.Server) {
router := server.Router()
router.Get("/api/v1/resources", r.handler.ListResources)
router.Get("/api/v1/resources/{id}", r.handler.GetResource)
router.Group(func(r chi.Router) {
r.Use(middleware.Auth)
r.Post("/api/v1/resources", r.handler.CreateResource)
r.Put("/api/v1/resources/{id}", r.handler.UpdateResource)
r.Delete("/api/v1/resources/{id}", r.handler.DeleteResource)
})
}
Multiple Handlers
When a router logically owns routes across two related resources (e.g., a resource and its items), inject both handlers via the constructor.
type ResourceRouter struct {
resourceHandler *handler.ResourceHandler
itemHandler *handler.ItemHandler
}
func NewResourceRouter(
resourceHandler *handler.ResourceHandler,
itemHandler *handler.ItemHandler,
) *ResourceRouter {
return &ResourceRouter{
resourceHandler: resourceHandler,
itemHandler: itemHandler,
}
}
func (r *ResourceRouter) Setup(server *chi.Server) {
router := server.Router()
router.Get("/api/v1/resources", r.resourceHandler.ListResources)
router.Post("/api/v1/resources", r.resourceHandler.CreateResource)
router.Get("/api/v1/items", r.itemHandler.ListItems)
router.Post("/api/v1/items", r.itemHandler.CreateItem)
}
Fx Wiring
Add to internal/modules/<module>/fx.go. The fx.As(new(chi.Route)) and fx.ResultTags are required â they register the router into the routes group so the HTTP server discovers it automatically.
fx.Provide(
fx.Annotate(
router.NewResourceRouter,
fx.As(new(chi.Route)),
fx.ResultTags(`group:"routes"`),
),
),
Multiple routers in the same module:
fx.Provide(
fx.Annotate(
router.NewResourceRouter,
fx.As(new(chi.Route)),
fx.ResultTags(`group:"routes"`),
),
fx.Annotate(
router.NewItemRouter,
fx.As(new(chi.Route)),
fx.ResultTags(`group:"routes"`),
),
),
URL Path Conventions
- Version prefix:
/api/v1/ - Resource names: Plural nouns (
/resources,/contacts,/monitors) - Resource ID:
{id}path param (/resources/{id}) - Nested resources:
/resources/{id}/items - Nested with two IDs:
/resources/{resourceId}/items/{itemId} - Actions: Verb suffix for non-CRUD (
/resources/{id}/activate) - Bulk:
/resources/bulkwith appropriate HTTP method
HTTP Methods
GET: Retrieve (list or single)POST: Create, or trigger an actionPUT: Full updatePATCH: Partial updateDELETE: Remove
Naming Conventions
- Struct:
<Resource>Router(PascalCase) - Constructor:
New<Resource>Router - File:
<resource>_router.go(snake_case) - Handler methods: Match action â
ListResources,CreateResource,ActivateResource
Rules
- No standalone functions: When a file contains a struct with methods, do not add standalone functions. Use private methods on the struct instead.
- The struct holds only handler pointer(s) â no other state
- Constructor returns a pointer (
*ResourceRouter) Setupmethod signature is exactlySetup(server *chi.Server)â never deviate- Always call
server.Router()insideSetupto get the chi router - Every route must start with
/api/v1/ - Resource names in paths are plural nouns
- Fx wiring requires both
fx.As(new(chi.Route))andfx.ResultTags(\group:”routes”`)` - Imports: only
bricks/pkg/http/server/chiand the handler package (plus middleware if using route groups) - No comments in the file â the code is self-describing
- Run
make lintafter generating
Workflow
- Create
internal/modules/<module>/http/chi/router/<resource>_router.go - Define struct with handler field(s)
- Implement constructor
- Implement
Setup(server *chi.Server)with all routes - Add Fx wiring to
internal/modules/<module>/fx.go - Run
make lintandmake nilawayto ensure code quality and no nil pointer issues