Control Flow Guide
Last updated: October 6, 2025
Control Flow Guide
Master conditional logic and loops in your document templates for dynamic content generation.
Table of Contents
- if/else/end - Conditional Rendering
- range/end - Looping
- with/end - Context Setting
- Comparison Operators
- Logical Operators
- Real-World Examples
if/else/end - Conditional Rendering
Basic if Statement
Render content only when a condition is true:
{{if .IsPaid}} <span class="badge badge-success">PAID</span> {{end}}
Sample Data:
{ "IsPaid": true }
Output:
<span class="badge badge-success">PAID</span>
if/else Statement
Choose between two alternatives:
{{if .IsActive}} <span class="status-active">Active</span> {{else}} <span class="status-inactive">Inactive</span> {{end}}
Sample Data:
{ "IsActive": false }
Output:
<span class="status-inactive">Inactive</span>
if/else if/else Chain
Multiple conditions:
{{if eq .Status "completed"}} <span class="badge-success">✓ Completed</span> {{else if eq .Status "pending"}} <span class="badge-warning">⏱ Pending</span> {{else if eq .Status "cancelled"}} <span class="badge-danger">✗ Cancelled</span> {{else}} <span class="badge-info">• Unknown</span> {{end}}
Sample Data:
{ "Status": "pending" }
Output:
<span class="badge-warning">⏱ Pending</span>
Checking for Empty/Nil Values
{{if .Email}} <p>Contact: {{.Email}}</p> {{else}} <p>No contact email provided</p> {{end}} {{if .Items}} <p>{{len .Items}} items in cart</p> {{else}} <p>Cart is empty</p> {{end}}
Negation with not
{{if not .IsDeleted}} <div class="active-record"> <p>{{.Name}}</p> </div> {{end}}
range/end - Looping
Simple Array Iteration
Loop through array elements:
<ul> {{range .Tags}} <li>{{.}}</li> {{end}} </ul>
Sample Data:
{ "Tags": ["urgent", "important", "review"] }
Output:
<ul> <li>urgent</li> <li>important</li> <li>review</li> </ul>
Iterating Objects in Array
<table> <thead> <tr> <th>Product</th> <th>Price</th> <th>Quantity</th> </tr> </thead> <tbody> {{range .Products}} <tr> <td>{{.Name}}</td> <td>${{.Price}}</td> <td>{{.Quantity}}</td> </tr> {{end}} </tbody> </table>
Sample Data:
{ "Products": [ {"Name": "Widget", "Price": 19.99, "Quantity": 5}, {"Name": "Gadget", "Price": 29.99, "Quantity": 3} ] }
range with Index
Capture both index and value:
{{range $index, $item := .Items}} <div class="item-{{$index}}"> <p>Item #{{$index}}: {{$item.Name}}</p> </div> {{end}}
Sample Data:
{ "Items": [ {"Name": "First Item"}, {"Name": "Second Item"} ] }
Output:
<div class="item-0"> <p>Item #0: First Item</p> </div> <div class="item-1"> <p>Item #1: Second Item</p> </div>
range with else
Handle empty arrays:
<ul> {{range .Notifications}} <li>{{.Message}}</li> {{else}} <li>No notifications</li> {{end}} </ul>
Sample Data (empty):
{ "Notifications": [] }
Output:
<ul> <li>No notifications</li> </ul>
Nested range Loops
{{range .Categories}} <div class="category"> <h3>{{.Name}}</h3> <ul> {{range .Products}} <li>{{.Name}} - ${{.Price}}</li> {{end}} </ul> </div> {{end}}
Sample Data:
{ "Categories": [ { "Name": "Electronics", "Products": [ {"Name": "Laptop", "Price": 999}, {"Name": "Mouse", "Price": 25} ] }, { "Name": "Books", "Products": [ {"Name": "Go Programming", "Price": 45} ] } ] }
with/end - Context Setting
Basic with Statement
Set context for nested object access:
{{with .Customer}} <div class="customer"> <h2>{{.Name}}</h2> <p>{{.Email}}</p> <p>{{.Phone}}</p> </div> {{end}}
Sample Data:
{ "Customer": { "Name": "John Doe", "Email": "john@example.com", "Phone": "+1-555-1234" } }
Output:
<div class="customer"> <h2>John Doe</h2> <p>john@example.com</p> <p>+1-555-1234</p> </div>
with/else
Handle missing nested objects:
{{with .BillingAddress}} <div class="billing"> <p>{{.Street}}</p> <p>{{.City}}, {{.State}}</p> </div> {{else}} <p>No billing address on file</p> {{end}}
Accessing Parent Context in with
Use $
to access root context:
{{with .Order}} <div class="order"> <p>Order: {{.Number}}</p> <p>Company: {{$.CompanyName}}</p> <p>Customer: {{.CustomerName}}</p> </div> {{end}}
Sample Data:
{ "CompanyName": "Acme Corp", "Order": { "Number": "ORD-001", "CustomerName": "John Doe" } }
Output:
<div class="order"> <p>Order: ORD-001</p> <p>Company: Acme Corp</p> <p>Customer: John Doe</p> </div>
Comparison Operators
eq - Equal
{{if eq .Status "active"}} <span class="active">Active</span> {{end}} {{if eq .Count 0}} <p>No items</p> {{end}}
ne - Not Equal
{{if ne .Status "deleted"}} <div class="record">{{.Name}}</div> {{end}}
lt - Less Than
{{if lt .Stock 10}} <span class="low-stock">Low Stock!</span> {{end}}
le - Less Than or Equal
{{if le .Score 60}} <span class="fail">Failed</span> {{end}}
gt - Greater Than
{{if gt .Price 1000}} <span class="premium">Premium Item</span> {{end}}
ge - Greater Than or Equal
{{if ge .Age 18}} <p>Adult</p> {{end}}
Comparison Examples
<!-- Multiple comparisons --> {{if and (ge .Price 100) (le .Price 500)}} <span class="mid-range">Mid-range product</span> {{end}} {{if or (eq .Type "urgent") (eq .Type "critical")}} <span class="alert">High Priority!</span> {{end}}
Logical Operators
and - Logical AND
All conditions must be true:
{{if and .IsActive .IsPaid}} <span class="status-good">Active & Paid</span> {{end}} {{if and (gt .Stock 0) (le .Stock 10)}} <span class="low-stock">Running low</span> {{end}}
or - Logical OR
At least one condition must be true:
{{if or .IsAdmin .IsModerator}} <button>Edit</button> {{end}} {{if or (eq .Status "pending") (eq .Status "processing")}} <span class="in-progress">In Progress</span> {{end}}
not - Logical NOT
Negate a condition:
{{if not .IsDeleted}} <div class="active-item">{{.Name}}</div> {{end}} {{if not (eq .Status "archived")}} <button>Archive</button> {{end}}
Complex Conditions
{{if and (not .IsDeleted) (or .IsActive .IsPending)}} <div class="available-item"> <p>{{.Name}}</p> </div> {{end}}
Real-World Examples
Example 1: Invoice with Conditional Sections
<div class="invoice"> <h1>Invoice #{{.InvoiceNumber}}</h1> <!-- Payment status --> {{if .IsPaid}} <div class="paid-stamp"> <p>PAID</p> <p>Paid on: {{.PaidDate | dateFormat "Jan 2, 2006"}}</p> </div> {{else}} <div class="unpaid-notice"> <p>Payment Due: {{.DueDate | dateFormat "Jan 2, 2006"}}</p> {{if .IsOverdue}} <p class="overdue">OVERDUE</p> {{end}} </div> {{end}} <!-- Line items --> <table> {{range .Items}} <tr> <td>{{.Description}}</td> <td>{{.Quantity}}</td> <td>${{.Price | printf "%.2f"}}</td> <td>${{.Total | printf "%.2f"}}</td> {{if .IsDiscounted}} <td class="discount">-{{.DiscountPercent}}%</td> {{end}} </tr> {{end}} </table> <!-- Totals --> <div class="totals"> <p>Subtotal: ${{.Subtotal | printf "%.2f"}}</p> {{if gt .DiscountAmount 0}} <p>Discount: -${{.DiscountAmount | printf "%.2f"}}</p> {{end}} {{if gt .Tax 0}} <p>Tax ({{.TaxRate}}%): ${{.Tax | printf "%.2f"}}</p> {{end}} <p class="total">Total: ${{.Total | printf "%.2f"}}</p> </div> <!-- Notes --> {{with .Notes}} <div class="notes"> <h3>Notes</h3> <p>{{.}}</p> </div> {{end}} </div>
Example 2: Order Status Tracker
<div class="order-tracker"> <h2>Order #{{.OrderNumber}}</h2> <div class="status-timeline"> <!-- Order Placed --> <div class="step {{if .OrderPlaced}}completed{{end}}"> <span class="icon">✓</span> <p>Order Placed</p> {{if .OrderPlaced}} <p class="date">{{.PlacedDate | dateFormat "Jan 2, 3:04 PM"}}</p> {{end}} </div> <!-- Processing --> <div class="step {{if .IsProcessing}}active{{else if .Processed}}completed{{end}}"> <span class="icon">{{if .Processed}}✓{{else}}⏱{{end}}</span> <p>Processing</p> {{if .Processed}} <p class="date">{{.ProcessedDate | dateFormat "Jan 2, 3:04 PM"}}</p> {{end}} </div> <!-- Shipped --> <div class="step {{if .IsShipping}}active{{else if .Shipped}}completed{{end}}"> <span class="icon">{{if .Shipped}}✓{{else}}📦{{end}}</span> <p>Shipped</p> {{if .Shipped}} <p class="date">{{.ShippedDate | dateFormat "Jan 2, 3:04 PM"}}</p> <p class="tracking">Tracking: {{.TrackingNumber}}</p> {{end}} </div> <!-- Delivered --> <div class="step {{if .Delivered}}completed{{end}}"> <span class="icon">{{if .Delivered}}✓{{else}}🏠{{end}}</span> <p>Delivered</p> {{if .Delivered}} <p class="date">{{.DeliveredDate | dateFormat "Jan 2, 3:04 PM"}}</p> {{end}} </div> </div> <!-- Cancellation notice --> {{if .IsCancelled}} <div class="cancelled-notice"> <p>This order was cancelled on {{.CancelledDate | dateFormat "Jan 2, 2006"}}</p> {{with .CancellationReason}} <p>Reason: {{.}}</p> {{end}} </div> {{end}} </div>
Example 3: Product Listing with Filters
<div class="product-listing"> <h1>{{.CategoryName}}</h1> {{range .Products}} {{if not .IsDiscontinued}} <div class="product"> <h3>{{.Name}}</h3> <!-- Price display --> {{if .OnSale}} <p class="price"> <span class="original">${{.OriginalPrice | printf "%.2f"}}</span> <span class="sale">${{.SalePrice | printf "%.2f"}}</span> <span class="savings">Save {{.SavingsPercent}}%</span> </p> {{else}} <p class="price">${{.Price | printf "%.2f"}}</p> {{end}} <!-- Stock status --> {{if eq .Stock 0}} <p class="out-of-stock">Out of Stock</p> {{else if lt .Stock 5}} <p class="low-stock">Only {{.Stock}} left!</p> {{else if le .Stock 20}} <p class="limited-stock">{{.Stock}} available</p> {{else}} <p class="in-stock">In Stock</p> {{end}} <!-- Features --> {{if .Features}} <ul class="features"> {{range .Features}} <li>{{.}}</li> {{end}} </ul> {{end}} <!-- Ratings --> {{if and .Rating (gt .Rating 0)}} <div class="rating"> <span class="stars">{{.Rating}} ★</span> {{if .ReviewCount}} <span class="reviews">({{.ReviewCount}} reviews)</span> {{end}} </div> {{end}} <!-- Badges --> <div class="badges"> {{if .IsNew}} <span class="badge-new">NEW</span> {{end}} {{if .IsBestseller}} <span class="badge-bestseller">BESTSELLER</span> {{end}} {{if .IsFeatured}} <span class="badge-featured">FEATURED</span> {{end}} </div> </div> {{end}} {{else}} <p class="no-products">No products available in this category.</p> {{end}} </div>
Example 4: Conditional Report Sections
<div class="report"> <h1>{{.ReportTitle}}</h1> <p class="period">Period: {{.StartDate | dateFormat "Jan 2"}} - {{.EndDate | dateFormat "Jan 2, 2006"}}</p> <!-- Executive Summary (always shown) --> <section class="summary"> <h2>Executive Summary</h2> <p>{{.Summary}}</p> </section> <!-- Sales Data (only if available) --> {{with .SalesData}} <section class="sales"> <h2>Sales Performance</h2> <p>Total Revenue: ${{.TotalRevenue | printf "%.2f"}}</p> {{if gt .GrowthRate 0}} <p class="positive">Growth: +{{.GrowthRate}}%</p> {{else if lt .GrowthRate 0}} <p class="negative">Decline: {{.GrowthRate}}%</p> {{else}} <p>No change from previous period</p> {{end}} {{if .TopProducts}} <h3>Top Products</h3> <ol> {{range .TopProducts}} <li>{{.Name}} - ${{.Revenue | printf "%.2f"}}</li> {{end}} </ol> {{end}} </section> {{end}} <!-- Customer Data (only if requested) --> {{if .IncludeCustomerData}} {{with .CustomerData}} <section class="customers"> <h2>Customer Insights</h2> <p>New Customers: {{.NewCustomers}}</p> <p>Returning Customers: {{.ReturningCustomers}}</p> {{if .ChurnRate}} {{if gt .ChurnRate 10}} <p class="warning">High churn rate: {{.ChurnRate}}%</p> {{else}} <p>Churn rate: {{.ChurnRate}}%</p> {{end}} {{end}} </section> {{end}} {{end}} <!-- Recommendations (conditional) --> {{if and .Recommendations (gt (len .Recommendations) 0)}} <section class="recommendations"> <h2>Recommendations</h2> <ul> {{range .Recommendations}} <li class="priority-{{.Priority}}">{{.Text}}</li> {{end}} </ul> </section> {{end}} </div>
Best Practices
- Keep Logic Simple: Move complex logic to your application, not templates
- Use with for Nested Objects: Makes templates cleaner and easier to read
- Handle Empty Cases: Always provide
else
branches for better user experience - Save Root Context: Use
$root := .
when nesting to access parent data - Validate Data: Check for nil/empty before accessing nested properties
- Use range/else: Handle empty arrays gracefully
- Comment Complex Logic: Use
{{/* comments */}}
to explain conditions
Common Patterns
Pattern 1: Show/Hide Sections
{{if .ShowSection}} <section>Content here</section> {{end}}
Pattern 2: Alternative Content
{{if .HasData}} <div>{{.Data}}</div> {{else}} <div>No data available</div> {{end}}
Pattern 3: Status-Based Styling
<div class="item status-{{.Status | lower}}"> {{if eq .Status "active"}} <!-- Active content --> {{else}} <!-- Inactive content --> {{end}} </div>
Pattern 4: Conditional Formatting
{{if gt .Amount 1000}} <span class="high-value">${{.Amount}}</span> {{else}} <span>${{.Amount}}</span> {{end}}
Next Steps
- Explore Barcode Generation
- Learn about Chart Generation
- Check out Starter Templates
Pro Tip: Test all conditional branches with different sample data to ensure your template handles all cases correctly!