I recognize that I am kicking a dead horse here, but…
With Hugo v0.123.0 and later you can range over an integer. That means you can range over a very big number: something less than or equal to 9223372036854775807. This allows us to simulate a loop that continues indefinitely until a break condition is met.
With my test site of approximately 10,000 pages, the code below is about 3x faster than using the shuffle
function. The random pages are unique and exclude the current page.
layouts/page.html
{{ define "main" }}
<h1>{{ .Title }}</h1>
{{/*
Create the page collection from which unique random pages will be selected
for listing. Using the partialCached function as shown below improves
performance with custom page collections, but is not required when using
built-in page collections such as .Pages and .RegularPages. The built-in page
collections are automatically cached upon their first use.
*/}}
{{ $pc := partialCached "create-page-collection.html" . }}
{{/* Set the number of unique random pages to be listed. */}}
{{ $n := 5 }}
{{/* Loop until we have listed the desired number of unique random pages. */}}
<p>Random pages:</p>
<ul>
{{ $randomPages := slice }}
{{ range 9223372036854775807 }}
{{ $p := index $pc (math.Rand | mul $pc.Len | math.Floor | int) }}
{{ if or (in $randomPages $p) (eq $p $) }}
{{ continue }}
{{ end }}
<li><a href="{{ $p.RelPermalink }}">{{ $p.LinkTitle }}</a></li>
{{ $randomPages = $randomPages | append $p }}
{{ if eq (len $randomPages) $n }}
{{ break }}
{{ end }}
{{ end }}
</ul>
{{ .Content }}
{{ end }}
{{ define "_partials/create-page-collection.html" }}
{{ return site.RegularPages }}
{{ end }}
In the next release you will be able to use the math.MaxInt64
function instead of the literal value 9223372036854775807.
For those who are interested, in English the number above is nine quintillion, two hundred twenty-three quadrillion, three hundred seventy-two trillion, thirty-six billion, eight hundred fifty-four million, seven hundred seventy-five thousand, eight hundred and seven.