Represent and transform data safely

Sum Values in a Go Slice with a Loop or `slices.Reduce`

Sum a Go int slice with a range loop, handle empty slices and arrays, and see when a third-party slices.Reduce helper is useful.

By Niko Minadze4 min read

Editorial illustration for How to Sum a Slice in Go—with a Loop or a Generic Helper

For one []int, start with a loop: set the total to zero, add each value, and return it. That is usually clearer than introducing a helper for a single calculation. If your project already uses a reducer, or you need to accumulate a result from elements of a different type, slices.Reduce offers another way to express the operation.

Sum an []int with range

This complete example passes an existing slice to SumInts and checks what happens with an empty slice:

package main

import "fmt"

func SumInts(values []int) int {
    total := 0
    for _, value := range values {
        total += value
    }
    return total
}

func main() {
    values := []int{2, 3, 4}
    fmt.Println(SumInts(values))  // 9
    fmt.Println(SumInts([]int{})) // 0

    array := [3]int{1, 2, 3}
    fmt.Println(SumInts(array[:])) // 6
}

A range over a slice supplies an index and a value on each iteration. The index is not needed for a total, so _ discards it. Go by Example’s range example uses the same zero-accumulator pattern and gets 9 from []int{2, 3, 4}.

The empty-slice result follows from the loop rather than a special case: there are no values to add, so total stays at zero. The function accepts a []int, so the named values slice is passed directly; no conversion or expansion is needed. For a one-off calculation, you could put the same loop at the call site. Naming it SumInts becomes useful when more than one caller needs that concrete operation.

Pass an array to a slice-taking function

The example also calls SumInts(array[:]). The slice expression supplies a []int argument from the array; passing the [3]int array value itself would not match the function’s []int parameter. Go can range over an array to sum it directly, but array[:] is the practical adaptation when the summing function already accepts a slice. Array length is part of an array’s type, whereas a slice type does not encode the collection’s length; Learn Go with Tests explains that distinction.

Use slices.Reduce when a callback helps

The following slices import is third-party: github.com/go-softwarelab/common/pkg/slices. Its documentation describes the package as complementing Go’s standard-library slices package. Do not assume an unqualified mention of slices refers to the same package in another file.

Here is the documented integer reduction, alongside a second calculation using struct elements:

package main

import (
    "fmt"

    "github.com/go-softwarelab/common/pkg/slices"
)

func main() {
    collection := []int{1, 2, 3, 4}
    sum := slices.Reduce(collection, func(agg int, item int) int {
        return agg + item
    }, 0)
    fmt.Println(sum) // 10

    type Product struct {
        Name  string
        Price int
    }
    products := []Product{
        {Name: "Apple", Price: 1},
        {Name: "Banana", Price: 2},
        {Name: "Cherry", Price: 3},
    }
    totalPrice := slices.Reduce(products, func(agg int, item Product) int {
        return agg + item.Price
    }, 0)
    fmt.Println(totalPrice) // 6
}

Reduce processes elements from left to right. In the first call, 0 is the initial accumulator, and the callback adds each int item to the running total. This is more machinery than the earlier loop for summing four integers. In the second call, though, the callback says exactly which part of each Product matters: it adds Price without first building a separate slice of prices.

The helper’s signature is Reduce[E any, R any](collection []E, accumulator func(agg R, item E) R, initial R) R. E is the slice element type; R is the accumulator and result type. The callback takes the current R and an E, then returns the next R. That is why the product call can read Product elements while keeping an int total. For more on the type-parameter notation itself, see Go Generics: How to Write Type Parameters, Constraints, and Generic Interfaces.

Choose the loop when the job is simply to total one []int: it shows the entire calculation without a callback or package dependency. Consider Reduce when its accumulator shape makes several calculations easier to read, particularly when the element and result types differ or the package is already in your project.

Comments

No comments yet.

Leave a comment

Your comment appears after approval. Plain text only; links stay as text. Line breaks and indentation are kept.

Up to 5,000 characters. No account or email needed.

All articles

Type at least two characters.

Press <kbd>Esc</kbd> to closeOpen the search page