Why does `and` process both expressions if the first one fails?

I have an if / else if / else statement, if a key isset and has a matching map in a data file, then execute, else fall to the else statement like the following. It works, but it throws error calling index: value is nil; should be of type string.

Why does it process the second expression if the value is not set?

        {{ if .Params.images.thumbnail }}
          <img src="{{ .Params.images.thumbnail }}" class="figure-img img-fluid" alt="{{ .Title }}">
        {{ else if and .Params.images.main (eq .Params.images.main "sectionSlug") }}
          <img src="/images/{{ .Section }}/{{ .Source.BaseFileName }}.jpg" class="figure-img img-fluid" alt="{{ .Title }}">
        {{ else if .Params.images.main }}
          <img src="{{ .Params.images.main }}" class="figure-img img-fluid" alt="{{ .Title }}">
        {{ else if and (isset .Params "ref_key") (index .Site.Data.images .Params.ref_key) }}
          {{ $imgs := index .Site.Data.images .Params.ref_key }}
          <img src="{{ $imgs.Thumbnail.Path }}" class="figure-img img-fluid" alt="{{ .Title }}">
        {{ else }}
          <img src="{{ .Site.Params.image }}" class="figure-img img-fluid" alt="{{ .Title }}">
        {{ end }}

As to why, you should ask Rob Pike in Google. I agree that it shouldn’t behave this way, but it’s probably too late to change.

So its an issue with Go’s template package?

The and operator is standard Go template syntax, so if both the conditions in “and false true” gets evaluated, that is part of Go’s logic.

As bep said, this is how the Go templates work right now. The workaround is to do something like this:

{{ else if and (isset .Params "ref_key") (index .Site.Data.images (index .Params "ref_key")) }}        
1 Like

Interesting, thanks for the workaround. I will give it a shot.