Introduction
Locky is a robust Role-Based Access Control (RBAC) service built with Go, designed to provide comprehensive user, group, member, and role management with fine-grained permissions.
Overview
Locky implements a multi-layered architecture that combines:
- JWT-based authentication for secure user identification
- Casbin RBAC for flexible authorization policies
- Redis caching for performance optimization
- MySQL/TiDB for persistent data storage
Key Features
- User Management: Complete CRUD operations for user accounts
- Group Management: Organize users into logical groups
- Member Management: Control group membership and relationships
- Role Management: Define and assign fine-grained permissions
- Multi-tier API: Public, Internal, and Private endpoints with different access levels
- Casbin Integration: Policy-based authorization with dual enforcer setup
- App-wide permissions (locky policies)
- Resource-specific permissions (resource policies)
Architecture Highlights
Locky follows a clean architecture pattern with clear separation of concerns:
- Client Layer: CLI tools for different user roles (Admin, App, Anonymous)
- API Layer: Gin-based HTTP router with middleware stack
- Controller Layer: Request handlers organized by access level
- Business Logic Layer: Use case implementations
- Repository Layer: Data access abstraction
- Data Layer: MySQL/TiDB, Redis, and Casbin policy storage
Use Cases
- Multi-tenant applications requiring organization-level access control
- Enterprise systems with complex permission requirements
- Microservices needing centralized authentication and authorization
- APIs requiring different access levels (public, internal, private)
Getting Started
See the Getting Started guide for installation and setup instructions.
Documentation Structure
This documentation is organized into the following sections:
- Architecture: Deep dive into system design and components
- API Reference: Complete API documentation with examples
- Configuration: Setup and configuration guides
- Development: Contributing and development workflows
- Appendix: Additional resources (Swagger, GoDoc)
High-Level Architecture
This page provides an overview of Locky's high-level architecture and how its components interact.
Architecture Diagram
System Layers
Locky is built on a multi-layered architecture that promotes separation of concerns and maintainability:
1. Client Layer
The client layer provides multiple CLI tools for different use cases:
- Admin CLI (
locky-client-admin): Administrative operations with elevated privileges - App CLI (
locky-client-app): Application-level operations for authenticated users - Anonymous CLI (
locky-client-anonymous): Public operations that don't require authentication
2. API Layer
The API layer handles HTTP requests and applies cross-cutting concerns:
- Gin Router: High-performance HTTP router and middleware framework
- Middleware Stack:
- JWT Authentication: Validates and decodes JWT tokens
- Casbin Authorization: Enforces RBAC policies
- Request Logger: Logs all incoming requests for auditing
3. Controller Layer
Controllers are organized by access level to enforce security boundaries:
- Public Controllers: Endpoints accessible without authentication (e.g., user registration, login)
- Internal Controllers: Endpoints for authenticated internal services
- Private Controllers: Endpoints requiring specific permissions
Each controller handles:
- User Controller: User account operations
- Group Controller: Group management
- Member Controller: Group membership operations
- Role Controller: Permission management
4. Business Logic Layer
Use cases implement business rules and orchestrate repository operations:
- User Usecase: User business logic
- Group Usecase: Group business logic
- Member Usecase: Membership business logic
- Role Usecase: Permission business logic
5. Repository Layer
Repositories abstract data access and provide a clean interface to the data layer:
- User Repository: User data operations
- Group Repository: Group data operations
- Member Repository: Membership data operations
- Role Repository: Role and permission operations (Casbin-backed)
- Common Repository: Shared operations (JWT token management)
- Redis Repository: Cache operations
6. Data Layer
The data layer consists of multiple storage systems:
- MySQL/TiDB: Primary relational database for users, groups, and members
- Redis: Caching layer for JWT token denylist and session management
- Casbin Policies: Authorization policy storage
- Locky Policy: Application-wide permissions
- Resource Policy: Resource-specific permissions
Data Flow
Authentication Flow
- User sends credentials to Public Controller (Login endpoint)
- Controller validates credentials via User Repository
- JWT token is generated and returned to client
- Subsequent requests include JWT token in Authorization header
- Middleware validates token and extracts user information
- Casbin enforcer checks user permissions
- Request proceeds to appropriate controller if authorized
Authorization Flow
Locky uses a dual-enforcer approach for fine-grained access control:
- App Enforcer (
etc/casbin/locky/): Controls access to API endpoints - Resource Enforcer (
etc/casbin/resources/): Controls access to specific resources
CRUD Operation Flow
- Client sends request through CLI
- Gin router routes to appropriate controller
- Middleware validates authentication and authorization
- Controller parses and validates request
- Use case applies business logic
- Repository performs database operations
- Response flows back through the layers
Configuration
The system is configured through:
- app.yaml: Main configuration file (database, Redis, JWT settings)
- Casbin Model Files: Define RBAC model structure
- Casbin Policy Files: Define actual permissions
Scalability Considerations
- Stateless API: JWT tokens enable horizontal scaling
- Redis Caching: Reduces database load
- Connection Pooling: Efficient database connection management
- Casbin Policy Caching: In-memory policy evaluation for fast authorization
Security Features
- JWT with HS256: Secure token-based authentication
- Token Denylist: Revoked tokens stored in Redis
- Casbin RBAC: Policy-based authorization
- Multi-tier Access: Public, Internal, and Private endpoint separation
- Admin Email Check: Additional verification for administrative operations
Next Steps
- Learn more about individual Components
- Explore the API Reference
- Review Configuration Guide
Components Overview
This section provides detailed information about each layer of the Locky architecture.
Layer Summary
| Layer | Purpose | Key Components |
|---|---|---|
| Client Layer | User interfaces and CLI tools | Admin CLI, App CLI, Anonymous CLI |
| API Layer | HTTP routing and middleware | Gin Router, JWT Auth, Casbin RBAC, Logger |
| Controller Layer | Request handling and validation | Public, Internal, Private Controllers |
| Business Logic Layer | Use cases and business rules | User, Group, Member, Role Usecases |
| Repository Layer | Data access abstraction | User, Group, Member, Role Repositories |
| Data Layer | Persistent storage | MySQL/TiDB, Redis, Casbin Policies |
Component Interaction
Each layer communicates with adjacent layers through well-defined interfaces:
Client → API → Controller → Business Logic → Repository → Data
Dependency Flow
- Downward Dependencies: Each layer depends only on the layer directly below it
- Interface-Based: Layers communicate through interfaces, not concrete implementations
- Testability: Each layer can be tested independently with mocks
Common Patterns
Repository Pattern
All data access goes through repositories, providing:
- Abstraction from underlying storage
- Consistent error handling
- Transaction management
- Query optimization
Use Case Pattern
Business logic is encapsulated in use cases:
- Single responsibility per use case
- Orchestration of multiple repositories
- Business rule validation
- Domain logic isolation
Middleware Pattern
Cross-cutting concerns are handled by middleware:
- Authentication
- Authorization
- Logging
- Error handling
Next Steps
Explore each layer in detail:
Client Layer
This page is under construction.
Api Layer
This page is under construction.
Controller Layer
This page is under construction.
Business Layer
This page is under construction.
Repository Layer
This page is under construction.
Data Layer
This page is under construction.
API Overview
Locky provides a RESTful API built with the Gin framework. The API is organized into three access levels to enforce security boundaries.
Base URL
http://localhost:8080/v1
Access Levels
Public Endpoints (/v1/public)
Public endpoints are accessible without authentication:
- User Registration: Create new user accounts
- User Login: Authenticate and receive JWT token
- Health Check: Service status
Internal Endpoints (/v1/internal)
Internal endpoints require JWT authentication and are intended for internal services:
- User Management: List, count, get user details
- Group Management: CRUD operations for groups
- Member Management: Manage group memberships
- Role Management: Query roles and permissions
Private Endpoints (/v1/private)
Private endpoints require both JWT authentication and specific Casbin permissions:
- User Administration: Update, delete users
- Group Administration: Full group management
- Member Administration: Full membership control
- Role Administration: Create, update, delete roles
Authentication
JWT Token
All authenticated endpoints require a JWT token in the Authorization header:
Authorization: Bearer <jwt_token>
Token Lifecycle
- Obtain Token: POST to
/v1/public/users/loginwith credentials - Use Token: Include in Authorization header for subsequent requests
- Token Expiry: Tokens expire after configured duration (default: 24 hours)
- Token Revocation: Logout endpoint adds token to Redis denylist
Authorization
Authorization is handled by Casbin with two policy sets:
App Policies (etc/casbin/locky/)
Controls access to API endpoints based on user roles.
Example policy:
p, admin, /v1/private/*, *
p, user, /v1/internal/users, GET
Resource Policies (etc/casbin/resources/)
Controls access to specific resources (groups, members).
Example policy:
p, user:123, group:456, read
p, user:123, group:456, write
Request/Response Format
Request Format
{
"name": "example",
"email": "user@example.com"
}
Response Format
{
"data": {
"id": 1,
"uuid": "f3b3b3b3-3b3b-3b3b-3b3b-3b3b3b3b3b3b",
"name": "example"
},
"message": "Success"
}
Error Format
{
"error": "Invalid credentials",
"code": 401
}
Rate Limiting
Currently, rate limiting is not implemented but can be added via middleware.
API Versioning
The API is versioned in the URL path (/v1/). Future versions will be released as /v2/, etc.
Next Steps
Authentication
This page is under construction.
Endpoints
This page is under construction.
Users
This page is under construction.
Groups
This page is under construction.
Members
This page is under construction.
Roles
This page is under construction.
Configuration Guide
Locky uses YAML-based configuration files for all runtime settings. This guide explains how to configure Locky for different environments.
Configuration Files
| File | Purpose | Status |
|---|---|---|
etc/app.yaml | Runtime configuration | Not in Git (local only) |
etc/app.yaml.example | Production template | In Git (template) |
etc/app.dev.yaml | Development defaults | In Git (for development) |
Quick Start
Development Setup
# Copy development configuration
cp etc/app.dev.yaml etc/app.yaml
# Or start with Docker Compose (auto-configured)
docker-compose up -d
Production Setup
# Create configuration from template
cp etc/app.yaml.example etc/app.yaml
# Edit with your actual credentials
vi etc/app.yaml
Configuration Sections
Server Configuration
Server:
host: "0.0.0.0"
port: 8080
jwt_secret: "your-secure-secret-256-bits"
jwt:
key: "your-jwt-key"
Important:
jwt_secret: Must be at least 256 bits (32 characters)jwt.key: Used for signing JWT tokens- Generate secure random values for production
Database Configuration
MySQL:
host: "mysql-host"
user: "mysql-user"
pass: "mysql-password"
port: 3306
db: "database-name"
max_idle_conns: 10
max_open_conns: 100
conn_max_lifetime: 3600
Connection Pool Settings:
max_idle_conns: Maximum idle connections (default: 10)max_open_conns: Maximum open connections (default: 100)conn_max_lifetime: Connection lifetime in seconds (default: 3600)
Redis Configuration
Redis:
host: "redis-host"
port: 6379
pass: "redis-password"
db: 0
Note: The db field accepts either integer or string format.
Casbin Configuration
Casbin:
app_model: "etc/casbin/locky/model.conf"
app_policy: "etc/casbin/locky/policy.csv"
resource_model: "etc/casbin/resources/model.conf"
resource_policy: "etc/casbin/resources/policy.csv"
Dual Enforcer Setup:
- App Enforcer: Controls API endpoint access
- Resource Enforcer: Controls resource-level permissions
Environment-Specific Configuration
Development
Development configuration (app.dev.yaml) includes:
- Localhost database connections
- Default credentials for Docker Compose
- Debug-friendly settings
Production
Production configuration must include:
- Secure JWT secrets (256+ bits)
- Production database credentials
- Redis credentials
- Appropriate connection pool sizes
- Production-grade Casbin policies
Security Best Practices
- Never commit
etc/app.yaml- It's in.gitignorefor a reason - Use environment variables for sensitive data (optional approach)
- Rotate JWT secrets regularly
- Use strong passwords for MySQL and Redis
- Limit connection pool sizes based on your infrastructure
- Review Casbin policies before deployment
Environment Variables (Alternative)
While Locky primarily uses YAML configuration, you can also use environment variables:
export LOCKY_JWT_SECRET="your-secret"
export LOCKY_MYSQL_PASSWORD="your-db-password"
export LOCKY_REDIS_PASSWORD="your-redis-password"
Validation
Validate your configuration before starting:
# Test database connection
go run cmd/server/main.go --config etc/app.yaml --validate
# Check Casbin policies
casbin-cli check etc/casbin/locky/model.conf etc/casbin/locky/policy.csv
Troubleshooting
Connection Errors
Error: dial tcp: lookup mysql-host: no such host
Solution: Verify hostname and network connectivity
JWT Errors
Error: jwt_secret must be at least 256 bits
Solution: Generate a longer secret:
openssl rand -base64 32
Casbin Errors
Error: failed to load casbin policy
Solution: Check file paths and CSV format in policy files
Next Steps
Environment
This page is under construction.
Casbin
This page is under construction.
Getting Started
This guide will help you get Locky up and running on your local machine.
Prerequisites
- Go 1.22+: Download
- MySQL 8.0+ or TiDB: Database server
- Redis 6.0+: Cache server
- Docker & Docker Compose (optional): For quick setup
Quick Start with Docker Compose
The fastest way to get started:
# Clone the repository
git clone https://github.com/ryo-arima/locky.git
cd locky
# Start MySQL and Redis
docker-compose up -d
# Copy development configuration
cp etc/app.dev.yaml etc/app.yaml
# Run database migrations (if any)
# TODO: Add migration commands
# Build the server
go build -o .bin/locky-server ./cmd/server/main.go
# Start the server
./.bin/locky-server
The server will start on http://localhost:8080.
Manual Setup
1. Install Dependencies
# Install Go dependencies
go mod download
go mod vendor
2. Setup Database
# Create MySQL database
mysql -u root -p
> CREATE DATABASE locky;
> CREATE USER 'locky'@'localhost' IDENTIFIED BY 'password';
> GRANT ALL PRIVILEGES ON locky.* TO 'locky'@'localhost';
> FLUSH PRIVILEGES;
3. Setup Redis
# Start Redis (macOS with Homebrew)
brew services start redis
# Or with Docker
docker run -d -p 6379:6379 redis:alpine
4. Configure Application
# Copy configuration template
cp etc/app.yaml.example etc/app.yaml
# Edit configuration
vi etc/app.yaml
Update the following sections:
- MySQL connection details
- Redis connection details
- JWT secrets
5. Build the Application
# Build all binaries
make build
# Or build individually
go build -o .bin/locky-server ./cmd/server/main.go
go build -o .bin/locky-client-admin ./cmd/client/admin/main.go
go build -o .bin/locky-client-app ./cmd/client/app/main.go
go build -o .bin/locky-client-anonymous ./cmd/client/anonymous/main.go
6. Run the Server
./.bin/locky-server
Verify Installation
Check Server Status
# Health check
curl http://localhost:8080/v1/public/health
# Expected response:
# {"status": "ok"}
Register a User
curl -X POST http://localhost:8080/v1/public/users/register \
-H "Content-Type: application/json" \
-d '{
"name": "Test User",
"email": "test@example.com",
"password": "securepassword"
}'
Login
curl -X POST http://localhost:8080/v1/public/users/login \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "securepassword"
}'
# Save the JWT token from response
export TOKEN="<jwt_token_here>"
Access Protected Endpoint
curl http://localhost:8080/v1/internal/users \
-H "Authorization: Bearer $TOKEN"
Using the CLI Clients
Admin Client
./.bin/locky-client-admin --help
App Client
./.bin/locky-client-app --help
Anonymous Client
./.bin/locky-client-anonymous --help
Makefile Commands
Locky includes a Makefile for common tasks:
# Build all binaries
make build
# Run tests
make test
# Clean build artifacts
make clean
# Generate documentation
make docs
# Start development environment
make dev-up
# Stop development environment
make dev-down
Development Workflow
- Make Changes: Edit source code
- Build:
make build - Test:
make test - Run:
./.bin/locky-server - Verify: Test with curl or CLI clients
Troubleshooting
Port Already in Use
# Find process using port 8080
lsof -i :8080
# Kill the process
kill -9 <PID>
Database Connection Failed
- Verify MySQL is running:
mysql -u root -p - Check credentials in
etc/app.yaml - Ensure database exists:
SHOW DATABASES;
Redis Connection Failed
- Verify Redis is running:
redis-cli ping - Check Redis host/port in configuration
- Test connection:
redis-cli -h localhost -p 6379
Casbin Policy Errors
- Verify policy files exist in
etc/casbin/ - Check CSV format (no trailing commas)
- Validate model syntax
Next Steps
Building
This page is under construction.
Testing
This page is under construction.
Contributing
This page is under construction.
Swagger Documentation
Locky provides comprehensive API documentation via Swagger/OpenAPI specification.
Accessing Swagger UI
GitHub Pages (Recommended)
View the interactive Swagger UI online:
📖 Open Swagger UI (Opens in new window)
Or use the relative link when browsing documentation: 📖 Open Swagger UI
Local Development
When running Locky locally, Swagger UI is available at:
http://localhost:8080/swagger/index.html
Swagger Files
The Swagger specification is maintained in:
- Source:
docs/swagger/swagger.yaml - Online: swagger.yaml
- Generated: Auto-generated from code annotations
Swagger Specification Overview
The Swagger specification includes:
API Information
- Title: Locky API
- Version: 1.0.0
- Base Path:
/v1 - Schemes: HTTP, HTTPS
- Consumes:
application/json - Produces:
application/json
Endpoints Documented
Public Endpoints
POST /v1/public/users/register- User registrationPOST /v1/public/users/login- User authenticationGET /v1/public/health- Health check
Internal Endpoints
GET /v1/internal/users- List usersGET /v1/internal/users/count- Count usersGET /v1/internal/users/{id}- Get user detailsGET /v1/internal/groups- List groupsGET /v1/internal/groups/count- Count groupsGET /v1/internal/members- List membersGET /v1/internal/roles- List roles
Private Endpoints
PUT /v1/private/users/{id}- Update userDELETE /v1/private/users/{id}- Delete userPOST /v1/private/groups- Create groupPUT /v1/private/groups/{id}- Update groupDELETE /v1/private/groups/{id}- Delete groupPOST /v1/private/members- Add memberDELETE /v1/private/members/{id}- Remove memberPOST /v1/private/roles- Create rolePUT /v1/private/roles/{id}- Update roleDELETE /v1/private/roles/{id}- Delete role
Data Models
The specification includes complete schemas for:
Request Models
UserRequest- User registration/updateGroupRequest- Group creation/updateMemberRequest- Member additionRoleRequest- Role creation/update
Response Models
User- User objectGroup- Group objectMember- Member objectRole- Role objectCount- Count response
Common Properties
All models include:
id- Unique identifier (uint64)uuid- UUID stringcreated_at- Creation timestampupdated_at- Last update timestampdeleted_at- Soft delete timestamp (nullable)
Using Swagger UI
Try Out API Endpoints
- Open Swagger UI in browser
- Click on an endpoint to expand
- Click "Try it out"
- Fill in parameters
- Click "Execute"
- View response
Authentication
For protected endpoints:
- Get JWT token via
/v1/public/users/login - Click "Authorize" button in Swagger UI
- Enter token in format:
Bearer <token> - Click "Authorize"
- Try protected endpoints
Generating Swagger Documentation
From Code Annotations
Locky uses swaggo/swag for generating Swagger docs from code comments:
# Install swag CLI
go install github.com/swaggo/swag/cmd/swag@latest
# Generate documentation
swag init -g cmd/server/main.go -o docs/swagger
# Documentation will be generated in docs/swagger/
Swagger Annotations Example
// @Summary Register a new user
// @Description Create a new user account
// @Tags users
// @Accept json
// @Produce json
// @Param request body entity.UserRequest true "User registration request"
// @Success 201 {object} entity.User
// @Failure 400 {object} map[string]string
// @Router /v1/public/users/register [post]
func (c *userController) Register(ctx *gin.Context) {
// Implementation
}
Swagger vs OpenAPI
- OpenAPI 3.0: Modern specification format
- Swagger 2.0: Legacy format (currently used by Locky)
- Migration: Consider upgrading to OpenAPI 3.0
Interactive Documentation
Swagger Editor
Edit the specification online:
- Visit Swagger Editor
- Paste contents of
docs/swagger/swagger.yaml - View formatted documentation
- Validate specification
Postman Integration
Import Swagger spec into Postman:
- Open Postman
- Click "Import"
- Select
docs/swagger/swagger.yaml - Use generated collection for testing
API Testing with Swagger
Swagger UI provides built-in testing:
- Authentication: Test login flow
- CRUD Operations: Test all endpoints
- Validation: Verify request/response schemas
- Error Handling: Test error scenarios
Best Practices
Maintaining Documentation
- Update Swagger annotations when changing APIs
- Regenerate docs after code changes
- Validate specification regularly
- Keep examples up-to-date
Documentation Quality
- Clear descriptions for all endpoints
- Comprehensive parameter documentation
- Example request/response bodies
- Document all error codes
Swagger Tools
CLI Tools
# Validate Swagger spec
swagger validate docs/swagger/swagger.yaml
# Generate client SDKs
swagger generate client -f docs/swagger/swagger.yaml
# Generate server code
swagger generate server -f docs/swagger/swagger.yaml
Online Validators
Next Steps
GoDoc
Locky's Go package documentation is generated using standard Go documentation tools.
Viewing GoDoc
GitHub Pages
📖 GoDoc Overview (Links to pkg.go.dev)
Or use the relative link when browsing documentation: 📖 GoDoc Overview
Online - pkg.go.dev (When Published)
Once the package is published, view the official Go documentation online:
Local Documentation
Generate and view documentation locally:
# Install godoc tool (if not already installed)
go install golang.org/x/tools/cmd/godoc@latest
# Start local documentation server
godoc -http=:6060
# Open in browser
open http://localhost:6060/pkg/github.com/ryo-arima/locky/
Generated HTML
Pre-generated HTML documentation is available in:
docs/godoc/
Package Structure
Main Packages
| Package | Description |
|---|---|
pkg/server | HTTP server implementation |
pkg/client | CLI client implementations |
pkg/config | Configuration management |
pkg/entity | Data models and DTOs |
Server Packages
| Package | Description |
|---|---|
pkg/server/controller | Request handlers |
pkg/server/middleware | Middleware components |
pkg/server/repository | Data access layer |
Entity Packages
| Package | Description |
|---|---|
pkg/entity/model | Database models |
pkg/entity/request | Request DTOs |
pkg/entity/response | Response DTOs |
Client Packages
| Package | Description |
|---|---|
pkg/client/controller | CLI command handlers |
pkg/client/repository | API client layer |
pkg/client/usecase | Client business logic |
Key Types and Functions
Configuration
// BaseConfig holds application configuration
type BaseConfig struct {
YamlConfig YamlConfig
DB *gorm.DB
}
// LoadConfig loads configuration from YAML file
func LoadConfig(path string) (*BaseConfig, error)
Server
// InitRouter initializes the Gin router with all routes and middleware
func InitRouter(conf config.BaseConfig) *gin.Engine
// Start starts the HTTP server
func Start(router *gin.Engine, port int) error
Repository
// UserRepository provides user data access
type UserRepository interface {
ListUsers(filters map[string]interface{}) ([]model.User, error)
GetUser(id uint) (*model.User, error)
CreateUser(user *model.User) error
UpdateUser(user *model.User) error
DeleteUser(id uint) error
}
Entity Models
// User represents a user account
type User struct {
ID uint `gorm:"primaryKey"`
UUID string `gorm:"uniqueIndex"`
Name string
Email string `gorm:"uniqueIndex"`
Password string
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `gorm:"index"`
}
Documentation Standards
Package Comments
Every package should have a package-level comment:
// Package server implements the HTTP server and routing logic.
//
// The server package provides:
// - Gin-based HTTP routing
// - Middleware integration (JWT, Casbin, logging)
// - Controller initialization
// - Repository wiring
//
// Example usage:
//
// config := config.LoadConfig("etc/app.yaml")
// router := server.InitRouter(config)
// server.Start(router, 8080)
package server
Function Comments
All exported functions must have documentation:
// ListUsers retrieves a list of users based on the provided filters.
//
// Filters can include:
// - name: Filter by name (partial match)
// - email: Filter by email (exact match)
// - limit: Maximum number of results
// - offset: Number of results to skip
//
// Returns a slice of User models and an error if the operation fails.
func (r *userRepository) ListUsers(filters map[string]interface{}) ([]model.User, error)
Type Comments
All exported types must be documented:
// User represents a user account in the system.
//
// Users can belong to multiple groups and have various roles
// that determine their permissions within the application.
type User struct {
ID uint `gorm:"primaryKey" json:"id"`
UUID string `gorm:"uniqueIndex" json:"uuid"`
Name string `json:"name"`
Email string `gorm:"uniqueIndex" json:"email"`
Password string `json:"-"` // Never serialize password
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt *time.Time `gorm:"index" json:"deleted_at,omitempty"`
}
Generating Documentation
Standard godoc
# Generate HTML documentation
godoc -html github.com/ryo-arima/locky > docs/godoc/index.html
# Generate documentation for specific package
godoc -html github.com/ryo-arima/locky/pkg/server > docs/godoc/server.html
pkgsite (Modern godoc)
# Install pkgsite
go install golang.org/x/pkgsite/cmd/pkgsite@latest
# Run local server
pkgsite -http=:6060
# View documentation
open http://localhost:6060/github.com/ryo-arima/locky
Documentation Best Practices
Writing Good Documentation
- Start with a summary: One-line description of what it does
- Explain the why: Not just what, but why it exists
- Provide examples: Show common usage patterns
- Document parameters: Explain each parameter's purpose
- Document return values: Explain what's returned and when
- Document errors: List possible error conditions
- Link related items: Reference related types/functions
Example Structure
// FunctionName does something specific.
//
// More detailed explanation of what the function does,
// why it exists, and how it should be used.
//
// Parameters:
// - param1: Description of first parameter
// - param2: Description of second parameter
//
// Returns:
// - result: Description of return value
// - error: Possible error conditions
//
// Example:
//
// result, err := FunctionName(arg1, arg2)
// if err != nil {
// log.Fatal(err)
// }
// fmt.Println(result)
func FunctionName(param1 string, param2 int) (result string, err error)
Package Dependencies
View package dependencies:
# Generate dependency graph
go mod graph
# Visualize with graphviz
go mod graph | dot -Tsvg -o docs/dependencies.svg
Code Examples in Documentation
GoDoc supports executable examples:
// Example_listUsers demonstrates how to list users
func Example_listUsers() {
config := config.LoadConfig("etc/app.yaml")
repo := repository.NewUserRepository(config)
users, err := repo.ListUsers(map[string]interface{}{
"limit": 10,
})
if err != nil {
log.Fatal(err)
}
for _, user := range users {
fmt.Println(user.Name)
}
}
Testing Documentation
Verify documentation builds correctly:
# Check for documentation issues
go vet ./...
# Run documentation tests
go test -v ./...