Go Control Flow Check Skill
Purpose
Audit Go code for control flow best practices based on RMS Go coding standards. This skill identifies control flow anti-patterns and suggests refactoring opportunities to improve readability and maintainability.
What This Skill Checks
1. Early Return Pattern (Priority: HIGH)
Golden Rule: Use early returns for error cases and edge conditions to keep the happy path at the lowest indentation level.
Good Pattern:
func ProcessTask(task *Task) error {
if task == nil {
return errors.New("task is nil")
}
if !task.IsValid() {
return errors.New("invalid task")
}
// Happy path at lowest indentation
result := task.Execute()
return result.Save()
}
Bad Pattern:
func ProcessTask(task *Task) error {
if task != nil {
if task.IsValid() {
// Happy path nested 2 levels
result := task.Execute()
return result.Save()
} else {
return errors.New("invalid task")
}
} else {
return errors.New("task is nil")
}
}
2. Nesting Depth (Priority: HIGH)
Golden Rule: Maximum 2-3 levels of nesting. Deeper nesting indicates need for refactoring.
Detection Pattern:
- Count opening braces
{in nested structures - Flag any function with nesting > 3 levels
- Suggest extraction of nested logic into helper functions
3. Block Size (Priority: MEDIUM)
Golden Rule: If/else blocks should be < 10 lines. Large blocks need extraction.
Detection Pattern:
- Measure lines between
if {and closing} - Measure lines between
else {and closing} - Flag blocks > 10 lines for extraction
4. Guard Clauses (Priority: MEDIUM)
Golden Rule: Validate inputs and preconditions at function start with early returns.
Good Pattern:
func UpdateTask(ctx rms.Ctx, taskID string, updates map[string]interface{}) error {
// Guard clauses at top
if taskID == "" {
return errors.New("taskID required")
}
if len(updates) == 0 {
return errors.New("no updates provided")
}
// Main logic after guards
task, err := fetchTask(ctx, taskID)
// ...
}
5. Else Statements (Priority: LOW)
Guidance: Prefer early returns over else statements when possible.
Refactoring Pattern:
// Before
func IsValid(x int) bool {
if x > 0 {
return true
} else {
return false
}
}
// After
func IsValid(x int) bool {
if x > 0 {
return true
}
return false
}
Step-by-Step Execution
Step 1: Identify Go Files to Check
# Find all Go files in the repository
find . -name "*.go" -not -path "*/vendor/*" -not -path "*/mock*" -not -path "*_test.go"
Step 2: Read Target Go Files
Use the Read tool to examine Go files, focusing on:
- Function definitions
- Control flow structures (if/else, switch, for, select)
- Error handling patterns
Step 3: Analyze Each Function
For each function, check:
A. Early Return Pattern
- Identify error cases and edge conditions
- Verify they appear at function start with early returns
- Verify happy path is at lowest indentation
- Flag violations with line numbers
B. Nesting Depth
- Track indentation level as you scan through function
- Count maximum nesting depth
- Flag any depth > 3 levels
- Identify the nested section causing the issue
C. Block Size
- For each if/else block, count lines between braces
- Flag blocks > 10 lines
- Note what the block is doing (for extraction suggestion)
D. Guard Clauses
- Check if input validation is at function start
- Verify validations use early returns
- Flag missing guard clauses for required inputs
E. Unnecessary Else
- Find if-return followed by else-return patterns
- Suggest removing else and de-indenting
- Find if-return followed by else-continue logic patterns
Step 4: Generate Report
Create a structured report:
## Control Flow Audit: [file_path]
### ✅ Functions Following Best Practices
- `FunctionName` ([file:line]) - Early returns, minimal nesting
### ⚠️ Issues Found
#### HIGH Priority: Excessive Nesting
- **Function**: `ComplexFunction` ([file:line])
- **Issue**: Nesting depth of 4 levels at line X
- **Location**: Lines X-Y
- **Suggestion**: Extract nested logic into `helperFunction`
#### HIGH Priority: Missing Early Returns
- **Function**: `ProcessData` ([file:line])
- **Issue**: Happy path nested 2 levels, error checks not using early returns
- **Location**: Lines X-Y
- **Suggestion**: Add guard clauses at function start
#### MEDIUM Priority: Large Block
- **Function**: `HandleRequest` ([file:line])
- **Issue**: If block spans 15 lines (lines X-Y)
- **Suggestion**: Extract to `validateAndProcess` helper
#### LOW Priority: Unnecessary Else
- **Function**: `IsAuthorized` ([file:line])
- **Issue**: Else after return at line X
- **Suggestion**: Remove else, de-indent remaining code
Step 5: Suggest Refactoring
For each issue found, provide:
- Current code snippet (showing the problem)
- Refactored code snippet (showing the solution)
- Explanation (why the refactoring improves readability)
Step 6: Summary Statistics
## Summary
- Files checked: X
- Functions analyzed: Y
- Issues found: Z
- HIGH priority: A
- MEDIUM priority: B
- LOW priority: C
- Clean functions: W
Integration Points
This skill is invoked by:
quality-checkskill for Go projectssafe-commitskill (via quality-check)- Directly when refactoring Go code
Exit Criteria
- All Go functions analyzed
- Report generated with line-specific issues
- Refactoring suggestions provided for all issues
- Summary statistics calculated
Example Usage
# Manual invocation
/skill control-flow-check
# Automatic invocation via quality-check
/skill quality-check # Detects Go project, invokes control-flow-check
References
- RMS Go Coding Standards: Control Flow Excellence
- Go Code Reviewer Agent: Golden Rules
- Early Return Pattern: https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88
