`While` loop in a GoHugo template

I have a situation where I would need something akin to a while loop in other programming languages and have no idea how to realize that in a GoHugo template.

The following is a simplified example:

$I is 12345
$counter = 0
while $i > 1000
  $counter = $counter + 1
  $i = $i - 1000
end

and $counter would be 12 in the end and $I would be 345.

I think for this simple mathematical task I will probably end up doing something like $counter = $I / 1000 and then Math.floor it. But let’s assume with every step of this counter something more elaborate would have to be executed… How would we attempt that in GoHugo?

How you checked with and range ?

I have and both don’t do things “while the $I is larger than 1000”. While is more of a “take a slice out of the cake and do something” than “take one of x slices out and do something”. Technically speaking we don’t know how many instances of 1000 are in $I.

The seq function will create a slice with up to 2000 elements, so you’ll need to nest loops:

{{ $i := 12345 }}
{{ $c := 0 }}
{{ range seq 1000 }}
  {{ if lt $i 1000 }}
    {{ break }}
  {{ end }}
  {{ range seq 1000 }}
    {{ if lt $i 1000 }}
      {{ break }}
    {{ end }}
    {{ $i = sub $i 1000 }}
    {{ $c = add $c 1 }}
  {{ end }}
{{ end }}

{{ $c }} --> 12
{{ $i }} --> 345

Although breaking out of the inner loop is sufficient to produce the desired result, you should break out of both loops to avoid needless iterations.

Obviously we don’t need 1,000,000 iterations for your specific case, but the example above would accommodate “something more elaborate” (i.e., iterate forever, or something close to it, until a certain condition is met).

This would be a bit cleaner with a higher limit on the seq function. 2000 elements may seem a bit arbitrary, and perhaps too low, but we needed to pick something—a slice with a 1,000,000 elements requires a lot more memory.

1 Like

Your solution is quite elegant for my specific issue.

I feel like I should leave it at this point. It works. It solves my issue.

But also: we all agree that there is no way to do a simple “while” loop/range in Hugo (or even go?), right? I am not trying to sow dissent, but it feels like this functionality would be useful in any logical scripting language. For, If, While, etc. I don’t have the proper technical education to list all the “default methods” a programming language (or templating language) should or might provide, but doing some form of “do something with every single item of this collection” should be part of it?

PS: Googling this results in many posts a la “For is Golangs While”… So it’s back to understanding the inner workings of while I guess :smiley:

In Go everything’s a for loop:
https://go.dev/tour/flowcontrol/1

You would represent an infinite while loop with:

for {
  ...
}

The only loop construct in the text/template package is range.

That’s what range does.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.