Skip to content

Interpolation ​

Use { expr } to write the result of a Go expression into markup. gsx applies the safety rules for the surrounding text, attribute, URL, JavaScript, or CSS context; see Escaping.

Go expressions ​

Braces accept ordinary Go expressions: names, calls, arithmetic, conversions, method calls, and element values.

gsx
package views

component Greeting(name string, count int) {
	<p>Hello, { name }! You have { count } messages.</p>
}

Renders:

html
<p>Hello, World! You have 3 messages.</p>

▶ Open in Playground

{ name } writes a string and { count } writes a number. A gsx.Node renders as markup; other values are formatted according to their Go type.

Interpolating body literals ​

Use an f literal inside braces to mix authored text with @{ expr } holes. Each hole behaves like a separate { expr } interpolation in that body position.

gsx
package views

component Row(id string, n int) {
	<p>{f`row-@{id}-@{n}`}</p>
}

Renders:

html
<p>row-a&amp;b-5</p>

▶ Open in Playground

The f prefix is required. An unprefixed Go raw string such as {`plain @{text}`} contains no holes.

Delimiters and literal @{ ​

Both f`...` and f"..." create an interpolating literal. Choose the delimiter that makes the content easiest to read.

  • Inside a backtick-delimited literal, \` writes a literal backtick.
  • \@{ writes a literal @{ instead of opening a hole.

Using a literal as a Go value ​

An f literal is also a string expression, so it can initialize a variable or be passed to a function:

gsx
var name = "world"
var greeting = f`Hello, @{name}`

component Message() {
	<p>{ greeting }</p>
}

In direct body position, the surrounding text is authored markup and each hole is handled separately. As a Go value, the literal produces one string; if that string is later interpolated, the whole value follows the rules of its new context.

js and css literals also work as Go expressions, but retain the trusted types gsx.RawJS and gsx.RawCSS instead of becoming strings. See Contextual literals as Go values.

A literal or element literal nested inside a larger Go expression — wrap(f…) — works in every Go-expression position (attribute values, spreads, class/style parts, control-flow headers, and more). It evaluates in place, in Go's order and with Go's laziness:

gsx
<a href={withLocale(f`/items/@{id}`)}>…</a>

An error-carrying hole inside the literal is returned from Render (calls to its left still run first, as in Go), except on the right of &&/||, inside a func literal, in a for clause, in a case list, or in a {{ }} block — compute the value before the expression in those.

Fields and typed values ​

Field access uses ordinary Go syntax. Strings, booleans, numeric primitives, fmt.Stringer values, and renderable nodes keep their Go types until they are written.

gsx
package views

type User struct {
	Name string
	Age  int
}

component Profile(user User) {
	<p>{ user.Name } is { user.Age }</p>
}

Renders:

html
<p>Alice is 30</p>

▶ Open in Playground

Functions returning (T, error) ​

A call returning (T, error) needs no special marker. gsx writes the T value when the error is nil; otherwise the component's Render returns that error.

gsx
package views

func lookup(k string) (string, error) { return k, nil }

component Label(key string) {
	<span>{ lookup(key) }</span>
}

Renders:

html
<span>hello</span>

▶ Open in Playground

Only the two-value (T, error) shape is supported. Other multi-value results are reported as errors. To handle an error in the component instead of returning it, use an explicit Go if statement; see Control flow. The automatic rule applies when the call is a whole expression position; a pipeline applies it at any stage. Nested inside a larger Go expression, such as a struct-literal field or a function argument, the call is plain Go and does not compile: use an f literal hole for a string, or bind the value in a Go block first.

Component inputs ​

The same rule applies when a function call supplies a component input.

gsx
package views

func lookup(k string) (string, error) { return "val-" + k, nil }

component Row(label string) {
	<span>{ label }</span>
}

component Page(k string) {
	<Row label={lookup(k)}/>
}

Renders:

html
<span>val-item</span>

▶ Open in Playground

Multiple input expressions are evaluated in source order, and the first non-nil error stops rendering.

Choosing braces ​

TaskForm
Write a Go value{ expr }
Write text with per-hole values (body literals){f`...@{ expr }...`}
Render an element or fragment<tag>...</tag> or <>...</>
Run a Go statement without output{{ stmt }}

Element literals can also appear inside Go expressions; see Elements as values. For attribute values, see Attributes. For statement blocks and their scopes, see Raw Go.