The Go range keyword always walks a slice from low index to high index, so searches like golang reverse range, golang range reverse, go reverse range, golang range backwards, and reverse range golang really mean “choose an index strategy,” not a different range syntax. This page shows backward for loops, a forward range with a remapped index (still golang iterate slice backwards), mutating slices.Reverse for golang reverse slice / go reverse slice / reverse slice golang, a small generic helper, and an optional channel iterator. For ordinary forward passes, see iterate over a slice patterns (arrays and slices share the same loop forms).
Tested with Go 1.24 on Linux.
Classic reverse index loop
Count from len(s)-1 down to 0:
package main
import "fmt"
func main() {
intSlice := []int{12, 23, 9, 32, 182}
for i := len(intSlice) - 1; i >= 0; i-- {
fmt.Println(intSlice[i])
}
}Running it prints 182, 32, 9, 23, then 12 on separate lines.
Forward range with a remapped index
Here range still moves i from 0 upward, but you read s[len(s)-1-i] so values appear in reverse order. That is a common answer to golang range reverse when you want to keep a range header:
package main
import "fmt"
func main() {
intSlice := []int{12, 23, 9, 32, 182}
n := len(intSlice)
for i := range intSlice {
fmt.Println(intSlice[n-1-i])
}
}The printed sequence matches the first example.
slices.Reverse: reverse slice data, then range
Go 1.21 adds slices.Reverse, which reverses elements in place. If callers must keep the original order, clone first with slices.Clone:
package main
import (
"fmt"
"slices"
)
func main() {
orig := []int{12, 23, 9, 32, 182}
rev := slices.Clone(orig)
slices.Reverse(rev)
for _, v := range rev {
fmt.Println(v)
}
fmt.Println("orig unchanged:", orig)
}The loop over rev prints the same reverse order; orig stays [12 23 9 32 182].
Generic reverseIterate
A type parameter lets one helper print many slice types in reverse (see generics in Go):
package main
import "fmt"
func reverseIterate[T any](slice []T) {
for i := len(slice) - 1; i >= 0; i-- {
fmt.Printf("%v ", slice[i])
}
}
func main() {
reverseIterate([]int{12, 23, 9, 32, 182})
fmt.Println()
reverseIterate([]string{"This", "is", "reverse", "iterating", "example"})
fmt.Println()
}Sample output begins with 182 32 9 23 12 on the first line and the words of the string slice reversed on the second.
Optional: channel as a reverse iterator
You can stream elements in reverse order from a goroutine without reversing the backing array. This is rarely needed for simple printing but shows how channels can wrap a walk order:
package main
import "fmt"
func reverseStrings(slice []string) <-chan string {
ch := make(chan string)
go func() {
for i := range slice {
ch <- slice[len(slice)-1-i]
}
close(ch)
}()
return ch
}
func main() {
s := []string{"a", "b", "c", "d"}
for v := range reverseStrings(s) {
fmt.Println(v)
}
fmt.Println("original:", s)
}The channel yields d through a; s is still [a b c d].
Summary
Golang reverse range is not a special range form: use a decreasing index, remap inside range, call slices.Reverse (optionally on a slices.Clone) and then range forward, or factor a small generic reverseIterate. That covers golang iterate over slice in reverse as well as golang reverse slice when you really want data reversed versus only visiting indices backwards. Prefer the index loop or slices.Reverse for clarity; reach for channels when a pipeline already fits your design.
References
slicespackage documentation- Go generics tutorial
- Stack Overflow: iterate over a slice in reverse in Go

