Documentation
¶
Overview ¶
Package template provides a simple and efficient template engine for Go.
Package template provides a simple and efficient template engine for Go.
The template engine supports:
- Variable interpolation: {{ variable }}
- Filters: {{ variable|filter:arg }}
- Control structures: {% if condition %}, {% for item in collection %}
- Comments: {# comment #}
Basic Usage:
source := "Hello, {{ name|upper }}!"
parser := template.NewParser()
tpl, err := parser.Parse(source)
if err != nil {
panic(err)
}
ctx := template.NewContext()
ctx.Set("name", "world")
output, err := tpl.Execute(ctx)
// Output: "Hello, WORLD!"
Architecture:
The package is organized into several key components:
- Parser: Converts template strings into an AST (Abstract Syntax Tree)
- Grammar: Parses and evaluates conditional expressions
- Template: Executes the AST with a given context
- Filters: Transforms values during template execution
- Context: Stores and retrieves template variables
Control Flow:
The template engine supports break and continue statements within loops:
{% for item in items %}
{% if item == "skip" %}
{% continue %}
{% endif %}
{% if item == "stop" %}
{% break %}
{% endif %}
{{ item }}
{% endfor %}
Loop Context:
Within loops, a special "loop" variable is available providing:
- loop.Index: Current index (0-based)
- loop.Revindex: Reverse index
- loop.First: True if first iteration
- loop.Last: True if last iteration
- loop.Length: Total collection length
For detailed examples, see the examples/ directory.
Index ¶
- Constants
- Variables
- func ApplyFilters(value interface{}, fs []Filter, ctx Context) (interface{}, error)
- func Execute(tpl *Template, ctx Context) (string, error)
- func MustExecute(tpl *Template, ctx Context) string
- func RegisterFilter(name string, fn FilterFunc) error
- func Render(source string, ctx Context) (string, error)
- type BinaryExpressionNode
- type BooleanLiteralNode
- type Context
- type ContextBuilder
- type ControlFlow
- type ExpressionNode
- type Filter
- type FilterArg
- type FilterExpressionNode
- type FilterFunc
- type Grammar
- type Lexer
- type LoopContext
- type NilLiteralNode
- type Node
- type NumberArg
- type NumberLiteralNode
- type Parser
- type StringArg
- type StringLiteralNode
- type Template
- type Token
- type TokenType
- type UnaryExpressionNode
- type Value
- func (v *Value) Add(right *Value) (*Value, error)
- func (v *Value) And(right *Value) (*Value, error)
- func (v *Value) Divide(right *Value) (*Value, error)
- func (v *Value) Equal(right *Value) (*Value, error)
- func (v *Value) GreaterEqual(right *Value) (*Value, error)
- func (v *Value) GreaterThan(right *Value) (*Value, error)
- func (v *Value) In(haystack *Value) (*Value, error)
- func (v *Value) LessEqual(right *Value) (*Value, error)
- func (v *Value) LessThan(right *Value) (*Value, error)
- func (v *Value) Multiply(right *Value) (*Value, error)
- func (v *Value) NotEqual(right *Value) (*Value, error)
- func (v *Value) Or(right *Value) (*Value, error)
- func (v *Value) Subtract(right *Value) (*Value, error)
- type ValueType
- type VariableArg
- type VariableNode
Constants ¶
const ( NodeTypeBreak = "break" NodeTypeContinue = "continue" )
Node type constants
Variables ¶
var ( // ErrContextKeyNotFound is returned when a key is not found in the context. ErrContextKeyNotFound = errors.New("key not found in context") // ErrContextInvalidKeyType is returned when an unexpected type is encountered while navigating the context. ErrContextInvalidKeyType = errors.New("invalid key type for navigation") // ErrContextIndexOutOfRange is returned when an index is out of range in the context. ErrContextIndexOutOfRange = errors.New("index out of range in context") // ErrFilterNotFound indicates that the requested filter was not found in the global registry. ErrFilterNotFound = errors.New("filter not found") // ErrFilterInputInvalid indicates an issue with the filter input value being of an unexpected type or format. ErrFilterInputInvalid = errors.New("filter input is invalid") // ErrFilterArgsInvalid indicates an issue with the filter arguments, such as wrong type, format, or number of arguments. ErrFilterArgsInvalid = errors.New("filter arguments are invalid") // ErrFilterInputEmpty indicates that the input value is empty or nil. ErrFilterInputEmpty = errors.New("filter input is empty") // ErrInsufficientArgs indicates that the filter was called with insufficient arguments. ErrInsufficientArgs = errors.New("insufficient arguments provided") // ErrFilterInputNotSlice indicates a filter expected a slice but received a different type. ErrFilterInputNotSlice = errors.New("filter input is not a slice") // ErrFilterInputNotNumeric indicates a filter expected a numeric value but received a different type. ErrFilterInputNotNumeric = errors.New("filter input is not numeric") // ErrFilterInputInvalidTimeFormat indicates a filter expected a valid time format but didn't receive it. ErrFilterInputInvalidTimeFormat = errors.New("filter input has an invalid time format") // ErrFilterInputUnsupportedType indicates the filter received a type it does not support. ErrFilterInputUnsupportedType = errors.New("filter input is of an unsupported type") // ErrInvalidFilterName is returned when a filter name does not meet the required criteria. ErrInvalidFilterName = errors.New("invalid filter name") // ErrUnknownFilterArgumentType is returned when a filter argument type is unknown. ErrUnknownFilterArgumentType = errors.New("unknown argument type") // ErrUnknownNodeType is returned when an unexpected node type is encountered. ErrUnknownNodeType = errors.New("unknown node type") // ErrExpectedFilterName is returned when a filter name is expected after the pipe symbol. ErrExpectedFilterName = errors.New("expected filter name after '|'") // ErrInvalidNumber is returned when a number cannot be parsed. ErrInvalidNumber = errors.New("invalid number") // ErrExpectedRParen is returned when a right parenthesis is expected. ErrExpectedRParen = errors.New("expected ')'") // ErrUnexpectedToken is returned when an unexpected token is encountered. ErrUnexpectedToken = errors.New("unexpected token") // ErrUnsupportedType is returned when an unsupported type is encountered. ErrUnsupportedType = errors.New("unsupported type") // ErrUnsupportedOperator is returned when an unsupported operator is used. ErrUnsupportedOperator = errors.New("unsupported operator") // ErrUnsupportedUnaryOp is returned when an unsupported unary operator is used. ErrUnsupportedUnaryOp = errors.New("unsupported unary operator") // ErrUndefinedVariable is returned when a variable is not found in the context. ErrUndefinedVariable = errors.New("undefined variable") // ErrUndefinedProperty is returned when a property is not found in an object. ErrUndefinedProperty = errors.New("undefined property") // ErrNonStructProperty is returned when attempting to access a property on a non-struct value. ErrNonStructProperty = errors.New("cannot access property of non-struct value") // ErrCannotAccessProperty is returned when property access fails. ErrCannotAccessProperty = errors.New("cannot access property") // ErrCannotAddTypes is returned when attempting to add incompatible types. ErrCannotAddTypes = errors.New("cannot add values of these types") // ErrCannotSubtractTypes is returned when attempting to subtract incompatible types. ErrCannotSubtractTypes = errors.New("cannot subtract values of these types") // ErrCannotMultiplyTypes is returned when attempting to multiply incompatible types. ErrCannotMultiplyTypes = errors.New("cannot multiply values of these types") // ErrDivisionByZero is returned when attempting to divide by zero. ErrDivisionByZero = errors.New("division by zero") // ErrCannotDivideTypes is returned when attempting to divide incompatible types. ErrCannotDivideTypes = errors.New("cannot divide values of these types") // ErrCannotConvertToBool is returned when a value cannot be converted to boolean. ErrCannotConvertToBool = errors.New("cannot convert type to boolean") // ErrCannotCompareTypes is returned when attempting to compare incompatible types. ErrCannotCompareTypes = errors.New("cannot compare values of these types") // ErrInvalidIndexType is returned when an invalid type is used as an array index. ErrInvalidIndexType = errors.New("invalid index type") // ErrInvalidArrayIndex is returned when an array index is invalid. ErrInvalidArrayIndex = errors.New("invalid array index") // ErrIndexOutOfRange is returned when an array index is out of bounds. ErrIndexOutOfRange = errors.New("index out of range") // ErrUnsupportedArrayType is returned when an unsupported array type is encountered. ErrUnsupportedArrayType = errors.New("unsupported array type") // ErrNonObjectProperty is returned when attempting to access a property on a non-object value. ErrNonObjectProperty = errors.New("cannot access property of non-object") // ErrInvalidVariableAccess is returned when variable access is invalid. ErrInvalidVariableAccess = errors.New("invalid variable access") // ErrUnsupportedCollectionType is returned when an unsupported collection type is used in a for loop. ErrUnsupportedCollectionType = errors.New("unsupported collection type for for loop") // ErrUnexpectedCharacter is returned when the lexer encounters an unexpected character. ErrUnexpectedCharacter = errors.New("unexpected character") // ErrUnterminatedString is returned when a string literal is not properly terminated. ErrUnterminatedString = errors.New("unterminated string literal") // ErrIntegerOverflow is returned when an unsigned integer value exceeds the maximum int64 value. ErrIntegerOverflow = errors.New("unsigned integer value exceeds maximum int64 value") // ErrBreakOutsideLoop is returned when a break statement is used outside of a loop. ErrBreakOutsideLoop = errors.New("break statement outside of loop") // ErrContinueOutsideLoop is returned when a continue statement is used outside of a loop. ErrContinueOutsideLoop = errors.New("continue statement outside of loop") // ErrMultipleElseStatements indicates that multiple else statements are found in an if block ErrMultipleElseStatements = errors.New("multiple 'else' statements found in if block. Use 'elif' for additional conditions") )
Functions ¶
func ApplyFilters ¶
ApplyFilters executes a series of filters on a value within a context, supporting variable arguments.
func MustExecute ¶
MustExecute renders the template with provided context, ignoring errors.
func RegisterFilter ¶
func RegisterFilter(name string, fn FilterFunc) error
RegisterFilter adds a filter to the global registry with name validation.
Types ¶
type BinaryExpressionNode ¶ added in v0.2.0
type BinaryExpressionNode struct {
Left ExpressionNode
Right ExpressionNode
Operator string
}
BinaryExpressionNode represents a binary expression in the AST.
type BooleanLiteralNode ¶ added in v0.2.0
type BooleanLiteralNode struct {
Value bool
}
BooleanLiteralNode represents a boolean literal in the AST.
type Context ¶
type Context map[string]interface{}
Context stores template variables in a map structure, used for passing and accessing variables during template execution. Keys are strings, and values can be of any type, supporting dot-notation (.) for nested access.
func NewContext ¶
func NewContext() Context
NewContext creates and returns a new empty Context instance. Example usage: ctx := NewContext()
func (Context) Get ¶
Get retrieves a value from the Context for the specified key, supporting nested key access. Uses jsonpointer.Get to handle complex key paths, such as array indices and nested properties. Parameters:
- key: The key to retrieve, can be a dot-separated nested key like "user.profile.name"
Returns:
- interface{}: The retrieved value
- error: Returns an appropriate error if the key doesn't exist or access fails
func (Context) Set ¶
Set inserts a value into the Context with the specified key, supporting dot-notation (.) for nested keys. This method preserves original data types for top-level keys and creates minimal map structures only when needed for nested access. Relies on jsonpointer's powerful reading capabilities.
type ContextBuilder ¶ added in v0.3.6
type ContextBuilder struct {
// contains filtered or unexported fields
}
ContextBuilder provides a fluent API for building Context with error collection.
func NewContextBuilder ¶ added in v0.3.6
func NewContextBuilder() *ContextBuilder
NewContextBuilder creates a new ContextBuilder for fluent Context construction. Example usage:
ctx, err := NewContextBuilder().
KeyValue("name", "John").
Struct(user).
Build()
func (*ContextBuilder) Build ¶ added in v0.3.6
func (cb *ContextBuilder) Build() (Context, error)
Build returns the constructed Context and any errors collected during the build process. If there were any errors during KeyValue or Struct operations, they are returned as a joined error. Example:
ctx, err := NewContextBuilder().
KeyValue("name", "John").
Struct(user).
Build()
if err != nil {
// handle errors
}
func (*ContextBuilder) KeyValue ¶ added in v0.3.6
func (cb *ContextBuilder) KeyValue(key string, value interface{}) *ContextBuilder
KeyValue sets a key-value pair and returns the ContextBuilder to support method chaining. Example:
builder := NewContextBuilder().
KeyValue("name", "John").
KeyValue("age", 30)
func (*ContextBuilder) Struct ¶ added in v0.3.6
func (cb *ContextBuilder) Struct(v interface{}) *ContextBuilder
Struct expands struct fields into the Context using JSON serialization. The struct fields are flattened to top-level keys based on their json tags. Nested structs are preserved as nested maps and can be accessed using dot notation. If serialization fails, the error is collected and can be retrieved via Build().
Example:
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
builder := NewContextBuilder().Struct(User{Name: "John", Age: 30})
// Results in: context["name"]="John", context["age"]=30
// Template access: {{ name }}, {{ age }}
type ControlFlow ¶ added in v0.2.5
type ControlFlow int
ControlFlow represents the type of control flow operation
const ( // ControlFlowNone indicates no control flow change ControlFlowNone ControlFlow = iota // ControlFlowBreak indicates a break control flow ControlFlowBreak // ControlFlowContinue indicates a continue control flow ControlFlowContinue )
type ExpressionNode ¶ added in v0.2.0
ExpressionNode is the interface for all expression nodes
type FilterArg ¶
type FilterArg interface {
Value() interface{}
Type() string
}
FilterArg represents the interface for filter arguments.
type FilterExpressionNode ¶ added in v0.2.0
type FilterExpressionNode struct {
Expression ExpressionNode // Expression to be filtered
Filter string // Filter name and parameters
}
FilterExpressionNode defines filter expression node
type FilterFunc ¶
FilterFunc represents the signature of functions that can be applied as filters. Arguments are always passed as strings, even if the source in the template was a number literal or other type. Filter authors should parse string arguments into their expected types if necessary.
type Grammar ¶ added in v0.2.0
type Grammar struct {
// contains filtered or unexported fields
}
Grammar represents the parser structure
func NewGrammar ¶ added in v0.2.0
NewGrammar creates a new parser
func (*Grammar) Parse ¶ added in v0.2.0
func (g *Grammar) Parse() (ExpressionNode, error)
Parse starts parsing
type Lexer ¶ added in v0.2.0
type Lexer struct {
// contains filtered or unexported fields
}
Lexer tokenizes template expressions into a sequence of tokens.
type LoopContext ¶ added in v0.2.8
type LoopContext struct {
Index int // Current index (starting from 0)
Revindex int // Reverse index (length-1 to 0)
First bool // Whether this is the first iteration
Last bool // Whether this is the last iteration
Length int // Total length of the collection
}
LoopContext represents the loop information available in templates
type NilLiteralNode ¶ added in v0.3.1
type NilLiteralNode struct{}
NilLiteralNode represents a nil/null/none literal in the AST.
type Node ¶
type Node struct {
Type string
Text string
Variable string
Collection string
Filters []Filter
Children []*Node
EndText string
}
Node defines a single element within a template, such as text, variable, or control structure.
type NumberArg ¶
type NumberArg struct {
// contains filtered or unexported fields
}
NumberArg holds a number argument.
type NumberLiteralNode ¶ added in v0.2.0
type NumberLiteralNode struct {
Value float64
}
NumberLiteralNode represents a number literal in the AST.
type Parser ¶
type Parser struct{}
Parser analyzes template syntax.
func NewParser ¶
func NewParser() *Parser
NewParser creates a Parser with a compiled regular expression for efficiency.
type StringArg ¶
type StringArg struct {
// contains filtered or unexported fields
}
StringArg holds a string argument.
type StringLiteralNode ¶ added in v0.2.0
type StringLiteralNode struct {
Value string
}
StringLiteralNode represents a string literal in the AST.
type Template ¶
type Template struct {
Nodes []*Node
}
Template represents a structured template that can be executed with a given context.
func NewTemplate ¶
func NewTemplate() *Template
NewTemplate creates an empty template, ready to be populated with nodes.
func (*Template) Execute ¶
Execute combines template data with the provided context to produce a string.
func (*Template) MustExecute ¶
MustExecute combines template data with the provided context to produce a string, ignoring errors.
type Token ¶ added in v0.2.0
Token is a token in the template language. It represents a type and a value.
type TokenType ¶ added in v0.2.0
type TokenType int
TokenType represents the type of a token in the template language.
const ( // TokenIdentifier represents a variable identifier (e.g., user.age) TokenIdentifier TokenType = iota // TokenBool represents a boolean value (e.g., true, false) TokenBool // TokenNumber represents a number (e.g., 18) TokenNumber // TokenString represents a string constant TokenString // TokenOperator represents operators (e.g., ==, !=, <, >, &&, ||) TokenOperator // TokenArithOp represents arithmetic operators TokenArithOp // TokenNot represents the not operator (!) TokenNot // TokenLParen represents a left parenthesis (() TokenLParen // TokenRParen represents a right parenthesis ()) TokenRParen // TokenPipe represents the pipe operator (|) TokenPipe // TokenFilter represents a filter (including name and args, e.g., upper, truncate:30) TokenFilter // TokenEOF represents the end of input marker TokenEOF // TokenDot represents the dot operator (.) TokenDot )
type UnaryExpressionNode ¶ added in v0.2.0
type UnaryExpressionNode struct {
Operator string
Right ExpressionNode
}
UnaryExpressionNode represents a unary expression in the AST.
type Value ¶ added in v0.2.0
type Value struct {
Type ValueType
Int int64
Float float64
Str string
Bool bool
Slice interface{}
Map interface{}
Struct interface{}
}
Value defines the value type
func (*Value) GreaterEqual ¶ added in v0.2.0
GreaterEqual implements greater than or equal comparison
func (*Value) GreaterThan ¶ added in v0.2.0
GreaterThan implements greater than comparison
type ValueType ¶ added in v0.2.0
type ValueType int
ValueType represents the type of a value.
const ( // TypeInt represents an integer value type TypeInt ValueType = iota // TypeFloat represents a floating-point value type TypeFloat // TypeString represents a string value type TypeString // TypeBool represents a boolean value type TypeBool // TypeSlice represents a slice value type TypeSlice // TypeMap represents a map value type TypeMap // TypeNil represents a nil value type TypeNil // TypeStruct represents a struct value type TypeStruct )
type VariableArg ¶
type VariableArg struct {
// contains filtered or unexported fields
}
VariableArg holds a variable argument.
func (VariableArg) Type ¶
func (a VariableArg) Type() string
Type returns the argument type as "variable".
func (VariableArg) Value ¶
func (a VariableArg) Value() interface{}
Value returns the variable name.
type VariableNode ¶ added in v0.2.0
type VariableNode struct {
Name string
}
VariableNode represents a variable reference in the AST.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
context
command
Package main demonstrates template context usage.
|
Package main demonstrates template context usage. |
|
filter_with_args
command
Package main demonstrates template filters with arguments.
|
Package main demonstrates template filters with arguments. |
|
filters
command
Package main demonstrates template filter usage.
|
Package main demonstrates template filter usage. |
|
hello_world
command
Package main demonstrates a simple hello world template.
|
Package main demonstrates a simple hello world template. |
|
object
command
Package main demonstrates template object handling.
|
Package main demonstrates template object handling. |