Named ranges and the dot

I recently discovered (by bad coding I guess) that having a named range and using the dot inside the range magically works.

{{ range $index, $item := .Pages }}
  {{ $item.Title }} prints the title.
  {{ .Title }} does the same.
{{ end }}

Can this be trusted as one of Golang’s intricacies, or is it accidental and might disappear in the future?

1 Like

From what I understand, when you range with index, each $item got Title set, hence either, calling by $item.Title or short version .Title will work now and in future.

But if you worry about that, maybe this approach will help

{{ $title := or (.Title) ($item.Title) }}

and than requesting by {{ $title }}.

If one fail, second will be tried.

1 Like

I also expected that using $var := range like constructs (also eg for with) will not touch the .dot.

digging in the docs I found statements that these will always change the .dot.

It’s documented and changing that will be a big breaking change.

that said: I would trust in that it stays


Both doc pages state it generally that they bind the context directly at the top:

range / with

… binds context (the dot) to …

and later

Understanding context

At the top of a page template, the context (the dot) is a Page object. Within the range / with block, the context is bound to each successive element.

The code examples for the with function are more explicit on that:

Initialize a variable, scoped to the current block:

{{ with $var := 42 }}
  {{ . }} → 42
  {{ $var }} → 42
{{ end }}

and this one

With this contrived example:

{{ with 42 }}
  {{ .Title }}
{{ end }}

Hugo will throw an error:

1 Like