This document provides a comprehensive matrix of Go template patterns and their support status in LiveTemplate's AST-based template parser. All patterns have been systematically tested through 6 phases of fuzz testing with 60+ explicit test seeds and 2150+ baseline coverage patterns.
Test Coverage: ~95% of Go template features Fuzz Testing: Multi-layer infrastructure with TypeScript oracle validation, mutation testing, and invariant checking Last Updated: 2026-03-07
| Pattern | Status | Phase | Example | Notes |
|---|---|---|---|---|
| Simple field output | ✅ | Baseline | {{.Name}} |
Core feature |
| Nested field access | ✅ | Baseline | {{.User.Name}} |
Tested in multiple contexts |
| Comments | ✅ | Phase 5 | {{/* comment */}} |
Properly ignored during parsing |
| Empty templates | ✅ | Phase 5 | `` (empty string) | Handles gracefully |
| Comment-only templates | ✅ | Phase 5 | {{/* only comment */}} |
Valid template |
| Pattern | Status | Phase | Example | Notes |
|---|---|---|---|---|
| Leading trim | ✅ | Phase 5 | {{- .Field}} |
Removes preceding whitespace |
| Trailing trim | ✅ | Phase 5 | {{.Field -}} |
Removes following whitespace |
| Both sides trim | ✅ | Phase 5 | {{- .Field -}} |
Trims both sides |
| Trim in ranges | ✅ | Phase 5 | {{range .Items -}}\n{{end}} |
Works correctly |
| Negative number | ✅ | Phase 5 | {{-3}} |
Parsed as number, not trim |
| Trim with space | ✅ | Phase 5 | {{- 3}} |
Correctly identified as trim |
| Pattern | Status | Phase | Example | Notes |
|---|---|---|---|---|
| Simple if | ✅ | Baseline | {{if .Show}}yes{{end}} |
Basic conditional |
| If-else | ✅ | Baseline | {{if .Show}}yes{{else}}no{{end}} |
Both branches |
| Else-if chains | ✅ | Phase 2 | {{if .A}}a{{else if .B}}b{{else}}c{{end}} |
Multiple conditions |
| Nested if (2 levels) | ✅ | Baseline | {{if .A}}{{if .B}}nested{{end}}{{end}} |
Tested extensively |
| Nested if (10 levels) | ✅ | Deep nesting | Tested up to 10 levels | AST parser handles any depth |
| If with complex condition | ✅ | Phase 6 | {{if gt (len .Items) 0}}...{{end}} |
Function calls in condition |
| Pattern | Status | Phase | Example | Notes |
|---|---|---|---|---|
| Simple range | ✅ | Baseline | {{range .Items}}{{.}}{{end}} |
Core iteration |
| Range with else | ✅ | Phase 1 | {{range .Items}}item{{else}}empty{{end}} |
Empty state handling |
| Range with index | ✅ | Phase 3 | {{range $i, $v := .Items}}...{{end}} |
Variable declarations |
| Range with value only | ✅ | Phase 3 | {{range $v := .Items}}...{{end}} |
Single variable |
| Map range | ✅ | Phase 1 | {{range $k, $v := .Map}}...{{end}} |
Key-value iteration |
| Nested ranges | ✅ | Phase 2 | {{range .Outer}}{{range .Inner}}...{{end}}{{end}} |
2+ levels |
| Range + nested if | ✅ | Phase 2 | {{range .Items}}{{if .Active}}...{{end}}{{end}} |
Combined patterns |
| Empty slice | ✅ | Phase 1 | Data: []string{} |
Properly handles empty |
| Nil slice | ✅ | Phase 1 | Data: ([]string)(nil) |
Correctly treats as empty |
| Break statement | ✅ | Phase 2 | {{range .Items}}{{if ...}}{{break}}{{end}}{{end}} |
Go 1.18+ |
| Continue statement | ✅ | Phase 2 | {{range .Items}}{{if ...}}{{continue}}{{end}}{{end}} |
Go 1.18+ |
| Pattern | Status | Phase | Example | Notes |
|---|---|---|---|---|
| Simple with | ✅ | Baseline | {{with .User}}Hello {{.Name}}{{end}} |
Context switching |
| With-else | ✅ | Phase 2 | {{with .User}}user{{else}}no user{{end}} |
Nil handling |
| Nil value with | ✅ | Phase 1 | Data: nil |
Else branch triggered |
| Empty string with | ✅ | Phase 2 | Data: "" |
Falsy value |
| With + nested if | ✅ | Phase 2 | {{with .User}}{{if .Active}}...{{end}}{{end}} |
Complex nesting |
| Pattern | Status | Phase | Example | Notes |
|---|---|---|---|---|
| Variable declaration | ✅ | Phase 3 | {{$x := .Value}}{{$x}} |
Basic assignment |
| Context alias | ✅ | Phase 3 | {{$c := .}}{{$c.Field}} |
Alias for dot context; see internal/parse/var_decl_test.go |
| Variable reassignment | ✅ | Phase 3 | {{$x := ""}}{{$x = "new"}}{{$x}} |
In if/else blocks |
| Multiple variables | ✅ | Phase 3 | {{$a := .A}}{{$b := .B}}{{$a}}{{$b}} |
Multiple declarations |
| Range variables | ✅ | Phase 3 | {{range $i, $v := .Items}}{{$i}}: {{$v}}{{end}} |
Index and value |
| Variable shadowing | ✅ | Phase 3 | {{$v := .Name}}{{range .Items}}{{$v := .}}{{end}} |
Scoped correctly |
| Parent context access | ✅ | Phase 1, 3 | {{range .Items}}{{$.Title}}{{end}} |
$ for root |
| Nested context access | ✅ | Phase 3 | {{range}}{{range}}{{$$. Root}}{{end}}{{end}} |
Double $ |
| Pattern | Status | Phase | Example | Notes |
|---|---|---|---|---|
| Simple pipeline | ✅ | Baseline | {{.Name | printf "User: %s"}} |
Function call |
| Function with format | ✅ | Phase 6 | {{.Value | printf "%d"}} |
Type-specific formatting |
| Comparison: eq | ✅ | Phase 6 | {{if eq .A .B}}equal{{end}} |
Equality |
| Comparison: ne | ✅ | Phase 6 | {{if ne .A .B}}not equal{{end}} |
Inequality |
| Comparison: lt | ✅ | Phase 6 | {{if lt .Count 10}}small{{end}} |
Less than |
| Comparison: gt | ✅ | Phase 6 | {{if gt .Count 10}}large{{end}} |
Greater than |
| Comparison: le | ✅ | Phase 6 | {{if le .Count 5}}...{{end}} |
Less or equal |
| Comparison: ge | ✅ | Phase 6 | {{if ge .Count 5}}...{{end}} |
Greater or equal |
| Logical: and | ✅ | Phase 6 | {{if and .A .B}}both{{end}} |
Boolean AND |
| Logical: or | ✅ | Phase 6 | {{if or .A .B}}either{{end}} |
Boolean OR |
| Logical: not | ✅ | Phase 6 | {{if not .Empty}}has value{{end}} |
Boolean NOT |
| Function: len | ✅ | Phase 6 | {{len .Items}}, {{len .Name}} |
Length/count |
| Function: index | ✅ | Phase 6 | {{index .Items 0}} |
Array access |
| Complex expression | ✅ | Phase 6 | {{if and (gt .Count 0) (lt .Count 10)}}...{{end}} |
Nested functions |
| Data Type | Status | Phase | Example | Notes |
|---|---|---|---|---|
| String | ✅ | All phases | "TestName" |
Primary type |
| String slices | ✅ | All phases | []string{"a", "b", "c"} |
Iteration support |
| Integer | ✅ | Phase 4 | 5, 42 |
Numbers |
| Integer slices | ✅ | Phase 4 | []int{1, 2, 3} |
Numeric iteration |
| Boolean | ✅ | All phases | true, false |
Conditionals |
| Boolean slices | ✅ | Phase 4 | []bool{true, false} |
Boolean iteration |
| Maps (string→string) | ✅ | Phase 1, 4 | map[string]string |
Key-value |
| Maps (generic) | ✅ | Phase 4 | map[string]interface{} |
Any value type |
| Structs | ✅ | All phases | Custom struct types | Field access |
| Nested structs | ✅ | Phase 4 | User.Profile.Bio |
Deep nesting |
| Interfaces | ✅ | Phase 4 | []interface{}{"str", 42, true} |
Mixed types |
| Nil values | ✅ | Phase 1 | nil |
Proper handling |
| Nil slices | ✅ | Phase 1 | ([]string)(nil) |
Distinct from empty |
| Nil pointers | ✅ | Phase 4 | (*string)(nil) |
Safe dereference |
| Empty collections | ✅ | Phase 1 | []string{}, map[string]string{} |
Edge cases |
| Pattern | Status | Phase | Example | Notes |
|---|---|---|---|---|
| Range + other dynamics | ✅ | Phase 1 | {{.Title}}{{range .Items}}...{{end}}{{.Footer}} |
Critical fix |
| Multiple ranges | ✅ | Phase 1 | Multiple {{range}} blocks in template |
Independent ranges |
| If wrapping range | ✅ | Baseline | {{if .Show}}{{range .Items}}...{{end}}{{end}} |
Tested extensively |
| Range + if + with | ✅ | Phase 2 | Complex 3-way nesting | All combinations work |
| Pattern | Status | Notes |
|---|---|---|
{{define}} / {{template}} |
✅ | Automatically flattened via FlattenTemplate() in internal/parse/flatten.go |
{{block}} |
✅ | Resolved during flattening; equivalent to {{define}} + {{template}} |
| Circular template references | ❌ | Not supported, would cause infinite loop |
| Undefined template invocation | ❌ | Returns error from Go template engine |
Template composition is fully supported through automatic AST flattening. FlattenTemplate() walks the parsed template tree, identifies the entry point, and inlines all {{template}} invocations into a single flat template before tree generation.
| Pattern | Status | Notes |
|---|---|---|
| Built-in Go functions | ✅ | All standard functions supported |
| User-defined functions | ⚠️ | Must be registered with Go template engine |
| Method calls on data | ✅ | Works if methods are public |
| Scenario | Performance | Notes |
|---|---|---|
| Deep nesting (10+ levels) | ✅ Good | AST parser handles any depth |
| Large lists (1000+ items) | ✅ Good | Efficient tree generation |
| Complex mixed patterns | ✅ Good | Optimized for real-world templates |
| Whitespace-heavy templates | ✅ Good | Trimming works efficiently |
| Phase | Patterns Added | Cumulative Total | Key Features |
|---|---|---|---|
| Baseline | 10 seeds | 10 | Core field access, basic ranges/conditionals |
| Phase 1 | 10 seeds | 20 | Mixed templates, empty states, map ranges |
| Phase 2 | 10 seeds | 30 | Break/continue, else-if, nested ranges, with-else |
| Phase 3 | 6 seeds | 36 | Variable scope, parent context, shadowing |
| Phase 4 | 6 seeds | 42 | Maps, int/bool slices, mixed types, pointers |
| Phase 5 | 8 seeds | 50 | Whitespace trimming, edge cases, empty templates |
| Phase 6 | 11 seeds | 61 | Pipelines, comparison/logical functions, index/len |
Total Baseline Coverage: 2150 interesting inputs (after fuzzing) Fuzz Executions: Ongoing via multi-layer infrastructure (diff fuzzing, TypeScript oracle, mutation testing) Failures: 0 crashes, 0 structural errors
LiveTemplate employs multi-level validation for fuzz testing:
"s" (statics) keyorderedVars structure (internal/parse/vars.go) and sorted TreeNode iteration1. Mixed Templates (ranges + other dynamics)
<h1>{{.Title}}</h1>
{{range .Items}}
<div>{{.Name}}</div>
{{end}}
<footer>{{.Footer}}</footer>
Works perfectly after Phase 1 fix.
2. Empty State Handling
{{range .Items}}
<div>Item: {{.}}</div>
{{else}}
<p>No items to display</p>
{{end}}
Best practice for user-friendly empty states.
3. Variable Scoping
{{$title := .Title}}
{{range .Items}}
<div>{{$title}}: {{.}}</div>
{{end}}
Efficient for accessing outer context.
4. Parent Context Access
{{range .Items}}
<div>{{$.SiteTitle}} - {{.Name}}</div>
{{end}}
Alternative to variable declarations.
5. Template Composition
{{define "user"}}
<div>{{.Name}} - {{.Email}}</div>
{{end}}
{{template "user" .CurrentUser}}
Fully supported — automatically flattened before tree generation.
1. Deeply Nested Variables
{{range}}{{range}}{{range}}{{$$$.Field}}{{end}}{{end}}{{end}}
Use intermediate variables instead.
docs/fuzz-framework-design.mdfuzz_diff_test.go, fuzz_ts_oracle_test.gointernal/fuzz/ (app, invariants, mutations, generators)internal/parse/ packageinternal/parse/vars.gointernal/parse/flatten.goDocument Owner: LiveTemplate Core Team Last Updated: 2026-03-07 Next Review: When new Go template features are added Feedback: Report issues or unsupported patterns via GitHub issues
LiveTemplate's parser provides comprehensive support for Go template patterns with:
$c := . context aliasingAll standard Go template patterns are supported, including template composition ({{define}}/{{template}}/{{block}}). Performance is excellent across all tested scenarios.