Start learning free

LESSON 93 OF 338 · ARRAYS I

Updating Slice Elements in Go

Lesson Read the full explanation

The entries of slices are mutable and can be changed freely, using indices and the bracket notation, just like we do with static arrays:

names := []string{"Andy", "Mary", "Cody"}

names[0] = "Mircea"
names[2] = "Mike"

// names is now {"Mircea", "Mary", "Cody"}

Assignment
Follow the Coding Tutorial and let's play with some arrays.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 2
    Ctrl + Enter to check

    GO · ARRAYS I

    Updating Elements in Go, explained

    Assigning to an index

    The elements of a slice are variables, and you can assign to them whenever you like. The syntax is the same as for arrays: the slice's name, the index in square brackets, then = and the new value.

    names := []string{"Andy", "Mary", "Cody"}
    
    names[0] = "Mircea"
    names[2] = "Mike"
    fmt.Println(names)
    
    [Mircea Mary Mike]
    

    Two assignments replaced two elements, and the element at index 1 was left alone. The slice has the same length as before. Assigning to an index replaces a value; it never inserts or removes one. To add an element you use append, and to shorten a slice you re-slice it.

    The new value must have the slice's element type. Assigning a number to an element of a []string is a compile error.

    Updating from the old value

    To change an element based on what it holds now, read it on the right-hand side of the assignment:

    ages := []int{14, 32, 50, 21}
    
    ages[1] = ages[1] + 5
    fmt.Println(ages)
    
    [14 37 50 21]
    

    Go evaluates the right-hand side first, so ages[1] + 5 is 37, and that value is then written back into ages[1]. Go has a shorter form for this pattern: ages[1] += 5 means exactly the same. There are matching operators for the other arithmetic: -=, *=, /= and %=. For adding or subtracting 1, use ages[1]++ or ages[1]--.

    The exercise

    You start from these slices:

    fruits := []string{"mango", "kiwi", "grapefruit"}
    ages := []int{14, 32, 50, 21}
    
    1. Change the first fruit to "apple" by assigning to index 0.
    2. Add 5 to the second age by assigning ages[1] + 5 back to ages[1].
    fruits[0] = "apple"
    ages[1] = ages[1] + 5
    

    Afterwards fruits is apple, kiwi, grapefruit, and ages is 14, 37, 50, 21. The second item has index 1 because counting starts at 0, and the same zero-based numbering applies when you write to an element as when you read from it.

    Slices share their elements

    A slice does not own its elements. It refers to an underlying array. When you pass a slice to a function, or assign it to another variable, both names refer to the same elements, so an update through one is visible through the other:

    func bump(s []int) { s[0] += 100 }
    
    bump(ages)
    fmt.Println(ages)
    
    [114 37 50 21]
    

    This is the opposite of arrays, which are copied when passed. It is handy when a function should modify the data in place, and surprising when you expected a private copy. If you do need independent data, make a new slice of the same length and use copy:

    dup := make([]int, len(ages))
    copy(dup, ages)
    dup[0] = 0
    fmt.Println(ages, dup)
    
    [14 32 50 21] [0 32 50 21]
    

    Now dup has its own elements, and changing it does not affect ages.

    The same sharing applies to a part of a slice. After part := ages[1:3], the assignment part[0] = 0 sets ages[1] to 0, because index 0 of part is index 1 of ages.

    Updating every element

    To change every element, loop over the indices and assign through the slice:

    for i := range ages {
    	ages[i] *= 2
    }
    

    Writing for _, a := range ages { a *= 2 } would not work. The variable a is a copy of each element, so doubling it leaves the slice unchanged. The code compiles and runs, and the slice prints exactly as before.

    Common mistakes

    • Using an index that does not exist. Assigning to ages[4] on a four-element slice panics when it runs. A slice does not grow by assignment: use append.
    • Off-by-one indexing. The first item is index 0.
    • Updating the loop variable instead of the slice. In a range loop, the value variable is a copy. Assign through ages[i] when the slice itself must change.
    • Forgetting that data is shared. Changing a slice inside a function changes the caller's data.

    Key takeaways

    • s[i] = value replaces one element and keeps the length.
    • s[i] += n is shorthand for s[i] = s[i] + n.
    • Slices share their underlying array, so updates are visible everywhere the slice is used.
    • Loop with the index to update every element.
    Keep going with GoAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free