Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
R

raymond

> 编程语言
Open source

Handlebars for golang

643 stars0 likes0 views
WebsiteGitHub

About

Handlebars for golang

raymond

⚠️ Project is archived ⚠️

Handlebars for golang with the same features as handlebars.js 3.0.

The full API documentation is available here: .

Table of Contents

  • Quick Start
  • Correct Usage
  • Context
  • HTML Escaping
  • Helpers
    • Template Helpers
    • Built-In Helpers
      • The if block helper
      • The unless block helper
      • The each block helper
      • The with block helper
      • The lookup helper
      • The log helper
      • The equal helper
    • Block Helpers
      • Block Evaluation
      • Conditional
      • Else Block Evaluation
      • Block Parameters
    • Helper Parameters
      • Automatic conversion
    • Options Argument
      • Context Values
      • Helper Hash Arguments
      • Private Data
    • Utilites
      • Str()
      • IsTrue()
  • Context Functions
  • Partials
    • Template Partials
    • Global Partials
    • Dynamic Partials
    • Partial Contexts
    • Partial Parameters
  • Utility Functions
  • Mustache
  • Limitations
  • Handlebars Lexer
  • Handlebars Parser
  • Test
  • References
  • Others Implementations

Quick Start

$ go get github.com/aymerick/raymond

The quick and dirty way of rendering a handlebars template:

go
package main

import (
    "fmt"

    "github.com/aymerick/raymond"
)

func main() {
    tpl := `

`

    ctx := map[string]string{
        "title": "My New Post",
        "body":  "This is my first post!",
    }

    result, err := raymond.Render(tpl, ctx)
    if err != nil {
        panic("Please report a bug :)")
    }

    fmt.Print(result)
}

Displays:

xml

Please note that the template will be parsed everytime you call Render() function. So you probably want to read the next section.

Correct Usage

To avoid parsing a template several times, use the Parse() and Exec() functions:

…

Displays:

xml

You can use MustParse() and MustExec() functions if you don't want to deal with errors:

go
// parse template
tpl := raymond.MustParse(source)

// render template
result := tpl.MustExec(ctx)

Context

The rendering context can contain any type of values, including array, slice, map, struct and func.

When using structs, be warned that only exported fields are accessible. However you can access exported fields in template with their lowercase names. For example, both {{author.firstName}} and {{Author.FirstName}} references give the same result, as long as Author and FirstName are exported struct fields.

More, you can use the handlebars struct tag to specify a template variable name different from the struct field name.

…

Output:

xml

  
Comments

  
By Marcel Beliveau

  

HTML Escaping

By default, the result of a mustache expression is HTML escaped. Use the triple mustache {{{ to output unescaped values.

go
source := `

`

ctx := map[string]string{
    "title": "All about 
 Tags",
    "body":  "
This is a post about &lt;p&gt; tags
",
}

tpl := raymond.MustParse(source)
result := tpl.MustExec(ctx)

fmt.Print(result)

Output:

xml

When returning HTML from a helper, you should return a SafeString if you don't want it to be escaped by default. When using SafeString all unknown or unsafe data should be manually escaped with the Escape method.

go
raymond.RegisterHelper("link", func(url, text string) raymond.SafeString {
    return raymond.SafeString("" + raymond.Escape(text) + "")
})

tpl := raymond.MustParse("{{link url text}}")

ctx := map[string]string{
    "url":  "http://www.aymerick.com/",
    "text": "This is a cool website",
}

result := tpl.MustExec(ctx)
fmt.Print(result)

Output:

xml
This is a &lt;em&gt;cool&lt;/em&gt; website

Helpers

Helpers can be accessed from any context in a template. You can register a helper with the RegisterHelper function.

For example:

xml

  
Comments

  {{#each comments}}
  
By {{fullName author}}

  

  {{/each}}

With this context and helper:

go
ctx := map[string]interface{}{
    "author": map[string]string{"firstName": "Jean", "lastName": "Valjean"},
    "body":   "Life is difficult",
    "comments": []map[string]interface{}{{
        "author": map[string]string{"firstName": "Marcel", "lastName": "Beliveau"},
        "body":   "LOL!",
    }},
}

raymond.RegisterHelper("fullName", func(person map[string]string) string {
    return person["firstName"] + " " + person["lastName"]
})

Outputs:

xml

  
Comments

  
By Marcel Beliveau

  

Helper arguments can be any type.

The following example uses structs instead of maps and produces the same output as the previous one:

xml

  
Comments

  {{#each comments}}
  
By {{fullName author}}

  

  {{/each}}

With this context and helper:

go
type Post struct {
    Author   Person
    Body     string
    Comments []Comment
}

type Person struct {
    FirstName string
    LastName  string
}

type Comment struct {
    Author Person
    Body   string
}

ctx := Post{
    Person{"Jean", "Valjean"},
    "Life is difficult",
    []Comment{
        Comment{
            Person{"Marcel", "Beliveau"},
            "LOL!",
        },
    },
}

raymond.RegisterHelper("fullName", func(person Person) string {
    return person.FirstName + " " + person.LastName
})

You can unregister global helpers with RemoveHelper and RemoveAllHelpers functions:

go
raymond.RemoveHelper("fullname")
go
raymond.RemoveAllHelpers()

Template Helpers

You can register a helper on a specific template, and in that case that helper will be available to that template only:

go
tpl := raymond.MustParse("User: {{fullName user.firstName user.lastName}}")

tpl.RegisterHelper("fullName", func(firstName, lastName string) string {
  return firstName + " " + lastName
})

Built-In Helpers

Those built-in helpers are available to all templates.

The if block helper

You can use the if helper to conditionally render a block. If its argument returns false, nil, 0, "", an empty array, an empty slice or an empty map, then raymond will not render the block.

xml

When using a block expression, you can specify a template section to run if the expression returns a falsy value. That section, marked by {{else}} is called an "else section".

xml

You can chain several blocks. For example that template:

xml
{{#if isActive}}
  
{{else if isInactive}}
  
{{else}}
  
{{/if}}

With that context:

go
ctx := map[string]interface{}{
    "isActive":   false,
    "isInactive": false,
}

Outputs:

xml
 

The unless block helper

You can use the unless helper as the inverse of the if helper. Its block will be rendered if the expression returns a falsy value.

xml

The each block helper

You can iterate over an array, a slice, a map or a struct instance using this built-in each helper. Inside the block, you can use this to reference the element being iterated over.

For example:

xml

  {{#each people}}
    
{{this}}

  {{/each}}

With this context:

go
map[string]interface{}{
    "people": []string{
        "Marcel", "Jean-Claude", "Yvette",
    },
}

Outputs:

xml

  
Marcel

  
Jean-Claude

  
Yvette

You can optionally provide an {{else}} section which will display only when the passed argument is an empty array, an empty slice or an empty map (a struct instance is never considered empty).

xml
{{#each paragraphs}}
  
{{this}}

{{else}}
  
No content

{{/each}}

When looping through items in each, you can optionally reference the current loop index via {{@index}}.

xml
{{#each array}}
  {{@index}}: {{this}}
{{/each}}

Additionally for map and struct instance iteration, {{@key}} references the current map key or struct field name:

xml
{{#each map}}
  {{@key}}: {{this}}
{{/each}}

The first and last steps of iteration are noted via the @first and @last variables.

The with block helper

You can shift the context for a section of a template by using the built-in with block helper.

xml

With this context:

go
map[string]interface{}{
    "title": "My first post!",
    "author": map[string]string{
        "firstName": "Jean",
        "lastName":  "Valjean",
    },
}

Outputs:

xml

You can optionally provide an {{else}} section which will display only when the passed argument is falsy.

xml
{{#with author}}
  
{{name}}

{{else}}
  
No content

{{/with}}

The lookup helper

The lookup helper allows for dynamic parameter resolution using handlebars variables.

xml
{{#each bar}}
  {{lookup ../foo @index}}
{{/each}}

The log helper

The log helper allows for logging while rendering a template.

xml
{{log "Look at me!"}}

Note that the handlebars.js @level variable is not supported.

The equal helper

The equal helper renders a block if the string version of both arguments are equals.

For example that template:

xml
{{#equal foo "bar"}}foo is bar{{/equal}}
{{#equal foo baz}}foo is the same as baz{{/equal}}
{{#equal nb 0}}nothing{{/equal}}
{{#equal nb 1}}there is one{{/equal}}
{{#equal nb "1"}}everything is stringified before comparison{{/equal}}

With that context:

go
ctx := map[string]interface{}{
    "foo": "bar",
    "baz": "bar",
    "nb":  1,
}

Outputs:

xml
foo is bar
foo is the same as baz

there is one
everything is stringified before comparison

Block Helpers

Block helpers make it possible to define custom iterators and other functionality that can invoke the passed block with a new context.

Block Evaluation

As an example, let's define a block helper that adds some markup to the wrapped text.

xml

The bold helper will add markup to make its text bold.

go
raymond.RegisterHelper("bold", func(options *raymond.Options) raymond.SafeString {
    return raymond.SafeString(`
")
})

A helper evaluates the block content with current context by calling options.Fn().

If you want to evaluate the block with another context, then use options.FnWith(ctx), like this french version of built-in with block helper:

go
raymond.RegisterHelper("avec", func(context interface{}, options *raymond.Options) string {
    return options.FnWith(context)
})

With that template:

xml
{{#avec obj.text}}{{this}}{{/avec}}

Conditional

Let's write a french version of if block helper:

go
source := `{{#si yep}}YEP !{{/si}}`

ctx := map[string]interface{}{"yep": true}

raymond.RegisterHelper("si", func(conditional bool, options *raymond.Options) string {
    if conditional {
        return options.Fn()
    }
    return ""
})

Note that as the first parameter of the helper is typed as bool an automatic conversion is made if corresponding context value is not a boolean. So this helper works with that context too:

go
ctx := map[string]interface{}{"yep": "message"}

Here, "message" is converted to true because it is an non-empty string

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Gogohandlebars

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言