Cursor rules for Go backend development with standard library patterns and clean architecture.
.cursorrules in your project rootYou are an expert Go developer following idiomatic patterns.
## Project Structure
```
├── cmd/
│ └── server/
│ └── main.go # Entry point
├── internal/
│ ├── config/ # Configuration
│ ├── handler/ # HTTP handlers
│ ├── service/ # Business logic
│ ├── repository/ # Data access
│ └── model/ # Domain models
├── pkg/ # Public packages
├── go.mod
└── go.sum
```
## Error Handling
```go
// ✅ Wrap errors with context
import "fmt"
func GetUser(id string) (*User, error) {
user, err := db.FindUser(id)
if err != nil {
return nil, fmt.Errorf("get user %s: %w", id, err)
}
return user, nil
}
// ✅ Define sentinel errors
var (
ErrNotFound = errors.New("not found")
ErrInvalidInput = errors.New("invalid input")
)
// ✅ Check error types
if errors.Is(err, ErrNotFound) {
// Handle not found
}
```
## HTTP Handlers
```go
type Handler struct {
userService UserService
logger *slog.Logger
}
func (h *Handler) GetUser(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
id := r.PathValue("id") // Go 1.22+
user, err := h.userService.Get(ctx, id)
if err != nil {
if errors.Is(err, ErrNotFound) {
h.writeError(w, http.StatusNotFound, "User not found")
return
}
h.logger.Error("failed to get user", "error", err, "id", id)
h.writeError(w, http.StatusInternalServerError, "Internal error")
return
}
h.writeJSON(w, http.StatusOK, user)
}
func (h *Handler) writeJSON(w http.ResponseWriter, status int, data any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(data)
}
func (h *Handler) writeError(w http.ResponseWriter, status int, message string) {
h.writeJSON(w, status, map[string]string{"error": message})
}
```
## Concurrency
```go
// ✅ Use context for cancellation
func ProcessItems(ctx context.Context, items []Item) error {
g, ctx := errgroup.WithContext(ctx)
for _, item := range items {
item := item // Capture loop variable
g.Go(func() error {
return processItem(ctx, item)
})
}
return g.Wait()
}
// ✅ Use channels for communication
func worker(jobs <-chan Job, results chan<- Result) {
for job := range jobs {
results <- process(job)
}
}
// ✅ Protect shared state with mutex
type Counter struct {
mu sync.Mutex
count int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.count++
}
```
## Interfaces
```go
// ✅ Define interfaces where used
type UserRepository interface {
Get(ctx context.Context, id string) (*User, error)
Create(ctx context.Context, user *User) error
}
// ✅ Accept interfaces, return structs
func NewUserService(repo UserRepository) *UserService {
return &UserService{repo: repo}
}
```Comprehensive Cursor rules for Next.js 14+ with App Router, including routing, layouts, and API patterns.
Cursor rules for TypeScript with strict type checking, advanced patterns, and best practices.
Cursor rules for Tailwind CSS development with responsive design, custom components, and dark mode.
Cursor
backend
AI coding rules customize how Cursor generates and refactors code for your project. Follow these steps to install Go Backend Development.
.cursor/rules, for Windsurf use .windsurfrulesComprehensive Cursor rules for Next.js 14+ with App Router, including routing, layouts, and API patterns.
Cursor rules for TypeScript with strict type checking, advanced patterns, and best practices.
Cursor rules for Tailwind CSS development with responsive design, custom components, and dark mode.