AI Rules for Go
Guide for effective AI interaction patterns when working with Go code.
Go Rules
.cusor/rules/go.mdc
---
description: Enforces best practices for Go development, focusing on context-aware code generation, modern patterns, and maintainable architecture. Provides comprehensive guidelines for writing clean, efficient, and secure Go code with proper context.
globs: **/*.go
---
# Go Best Practices
You are an expert in Go programming and related technologies.
You understand modern Go development practices, architectural patterns, and the importance of providing complete context in code generation.
### Context-Aware Code Generation
- Always provide complete package context including imports and package declarations
- Include relevant configuration files (go.mod, go.sum) when generating projects
- Generate complete function signatures with proper parameters and return values
- Include comprehensive GoDoc comments explaining the purpose, parameters, and return values
- Provide context about the package's role in the larger system architecture
- Follow proper package organization and module structure
### Code Style and Structure
- Follow Go style guide and clean code principles
- Structure code in logical packages following domain-driven design
- Implement proper separation of concerns (handlers, services, repositories)
- Use modern Go features (generics, error wrapping, context) appropriately
- Maintain consistent code formatting using gofmt
- Use proper interface design and composition
- Implement proper error handling with custom error types
- Use proper logging with structured data
### Type System and Interfaces
- Use proper type definitions and interfaces
- Implement proper interface segregation
- Use proper type assertions and type switches
- Implement proper custom types and methods
- Use proper type embedding and composition
- Implement proper type constraints with generics
- Use proper type aliases when appropriate
- Implement proper type safety patterns
### Testing and Quality
- Write comprehensive unit tests with proper test context
- Include integration tests for critical paths
- Use proper table-driven tests
- Implement proper test helpers and utilities
- Include performance tests for critical components
- Maintain high test coverage for core business logic
- Use proper test data factories
- Implement proper test doubles
- Use proper test organization with test packages
### Security and Performance
- Implement proper input validation and sanitization
- Use secure authentication and token management
- Configure proper CORS and CSRF protection
- Implement rate limiting and request validation
- Use proper caching strategies
- Optimize memory usage and garbage collection
- Implement proper error handling and logging
- Use proper data validation and sanitization
- Implement proper access control
### API Design
- Follow RESTful principles with proper HTTP methods
- Use proper status codes and error responses
- Implement proper versioning strategies
- Document APIs using OpenAPI/Swagger
- Include proper request/response validation
- Implement proper pagination and filtering
- Use proper serialization and deserialization
- Implement proper rate limiting
- Use proper API authentication
### Concurrency and Parallelism
- Use proper goroutine patterns
- Implement proper channel communication
- Use proper sync primitives
- Implement proper context cancellation
- Use proper worker pools
- Implement proper error handling in goroutines
- Use proper resource cleanup
- Implement proper backpressure
- Use proper concurrent data structures
### Build and Deployment
- Use proper module management
- Implement proper CI/CD pipelines
- Use Docker for containerization
- Configure proper environment variables
- Implement proper logging and monitoring
- Use proper deployment strategies
- Implement proper backup strategies
- Use proper monitoring tools
- Implement proper error tracking
### Examples
```go
// Package user provides user-related operations.
// It handles user management and authentication.
package user
import (
"context"
"encoding/json"
"errors"
"fmt"
"log"
)
// UserService handles user-related operations.
type UserService struct {
apiClient APIClient
cache Cache
logger *log.Logger
}
// NewUserService creates a new UserService instance.
func NewUserService(apiClient APIClient, cache Cache, logger *log.Logger) *UserService {
if logger == nil {
logger = log.Default()
}
return &UserService{
apiClient: apiClient,
cache: cache,
logger: logger,
}
}
// FindUserByEmail finds a user by their email address.
//
// Parameters:
// - ctx: context for cancellation and timeouts
// - email: the email address to search for
//
// Returns:
// - *User: the user if found
// - error: any error that occurred
func (s *UserService) FindUserByEmail(ctx context.Context, email string) (*User, error) {
// Check cache first
cachedUser, err := s.cache.Get(ctx, fmt.Sprintf("user:%s", email))
if err == nil && cachedUser != "" {
var user User
if err := json.Unmarshal([]byte(cachedUser), &user); err == nil {
return &user, nil
}
}
// Fetch from API
user, err := s.apiClient.GetUser(ctx, email)
if err != nil {
s.logger.Printf("Failed to find user by email: %v", err)
return nil, fmt.Errorf("failed to find user by email: %w", err)
}
// Cache the result
if user != nil {
userJSON, err := json.Marshal(user)
if err == nil {
_ = s.cache.Set(ctx, fmt.Sprintf("user:%s", email), string(userJSON))
}
}
return user, nil
}
// Tests for UserService functionality.
func TestUserService_FindUserByEmail(t *testing.T) {
tests := []struct {
name string
email string
cacheResponse string
apiResponse *User
apiError error
wantUser *User
wantError bool
}{
{
name: "user found in cache",
email: "[email protected]",
cacheResponse: `{"id":1,"email":"[email protected]"}`,
wantUser: &User{ID: 1, Email: "[email protected]"},
},
{
name: "user found via API",
email: "[email protected]",
apiResponse: &User{ID: 1, Email: "[email protected]"},
wantUser: &User{ID: 1, Email: "[email protected]"},
},
{
name: "user not found",
email: "[email protected]",
apiResponse: nil,
wantUser: nil,
},
{
name: "API error",
email: "[email protected]",
apiError: errors.New("API error"),
wantError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Setup
ctx := context.Background()
apiClient := &mockAPIClient{
getUserResponse: tt.apiResponse,
getUserError: tt.apiError,
}
cache := &mockCache{
getResponse: tt.cacheResponse,
}
service := NewUserService(apiClient, cache, nil)
// Execute
user, err := service.FindUserByEmail(ctx, tt.email)
// Verify
if tt.wantError {
if err == nil {
t.Error("expected error, got nil")
}
return
}
if err != nil {
t.Errorf("unexpected error: %v", err)
return
}
if !reflect.DeepEqual(user, tt.wantUser) {
t.Errorf("got user %v, want %v", user, tt.wantUser)
}
})
}
}