LiveTemplate Go Template Support Matrix

Overview

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


Support Status Legend


Template Pattern Support Matrix

1. Actions & Basic Syntax

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

2. Whitespace Handling

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

3. Control Flow: Conditionals

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

4. Control Flow: Ranges

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+

5. Control Flow: With

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

6. Variables

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 $

7. Pipelines & Functions

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

8. Data Types

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

9. Mixed Template Patterns

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

Template Composition

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.

Custom Functions

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

Performance Considerations

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

Testing Coverage by Phase

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


Validation Levels

LiveTemplate employs multi-level validation for fuzz testing:

Level 1: Structure Validation ✅

Level 2: Render Validation ✅

Level 3: Round-Trip Validation ✅

Level 4: Transition Validation ✅


Common Patterns & Best Practices

1. 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.

⚠️ Patterns to Avoid

1. Deeply Nested Variables

{{range}}{{range}}{{range}}{{$$$.Field}}{{end}}{{end}}{{end}}

Use intermediate variables instead.


References


Maintenance

Document 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


Summary

LiveTemplate's parser provides comprehensive support for Go template patterns with:

All standard Go template patterns are supported, including template composition ({{define}}/{{template}}/{{block}}). Performance is excellent across all tested scenarios.