The Go runtime is panicking because a program is trying to access an element in a slice or array using an index that doesn’t exist within its valid bounds. This is a fundamental error in how the program is managing its data structures, leading to an immediate halt.

Common Causes and Fixes

1. Off-by-One Error in Loop Iteration

  • Diagnosis: Examine for loops that iterate over slices or arrays. Look for conditions like i <= len(slice) or i < len(slice) + 1.
  • Cause: The loop condition allows the index i to reach a value equal to the length of the slice (or array), which is one position beyond the last valid index (which is len(slice) - 1).
  • Fix: Change the loop condition to i < len(slice).
    // Incorrect
    for i := 0; i <= len(mySlice); i++ {
        fmt.Println(mySlice[i]) // Panics when i == len(mySlice)
    }
    
    // Correct
    for i := 0; i < len(mySlice); i++ {
        fmt.Println(mySlice[i])
    }
    
    This ensures the index i never exceeds len(mySlice) - 1.

2. Incorrect Index Calculation with External Input

  • Diagnosis: If the index is derived from user input, network data, or configuration files, print the calculated index value just before the access.
  • Cause: External data might be malformed, providing an index that’s too large or negative. For instance, a user might submit 100 for an index in a slice of length 50.
  • Fix: Add validation checks for the index before using it.
    userInputIndex := getUserInput() // Assume this returns an int
    if userInputIndex < 0 || userInputIndex >= len(mySlice) {
        fmt.Println("Error: Invalid index provided.")
        // Handle error appropriately, e.g., return an error, skip operation
    } else {
        fmt.Println(mySlice[userInputIndex])
    }
    
    This prevents out-of-bounds access by ensuring the index is within the [0, len(mySlice)-1] range.

3. Accessing an Empty Slice or Array

  • Diagnosis: Check if the slice or array being accessed has a length of zero.
  • Cause: The program attempts to access slice[0] or array[0] when the slice/array is empty (len(slice) == 0). An empty slice has no valid indices.
  • Fix: Add a check for the length of the slice/array before attempting access.
    // Incorrect
    if mySlice != nil { // This check isn't enough if mySlice is just empty
        fmt.Println(mySlice[0]) // Panics if len(mySlice) == 0
    }
    
    // Correct
    if len(mySlice) > 0 {
        fmt.Println(mySlice[0])
    } else {
        fmt.Println("Slice is empty, cannot access element.")
    }
    
    This guards against accessing any index on a zero-length collection.

4. Incorrectly Sized Slices After Appending

  • Diagnosis: If the slice is modified using append, verify the size of the slice after the append operation and before subsequent access.
  • Cause: A common mistake is assuming a slice has grown to a certain size after an append, but the append operation itself might have failed to grow it as expected (e.g., due to capacity issues in complex scenarios, though less common for simple appends) or the logic using the appended element is flawed. More often, the index used to access the newly appended element is calculated incorrectly (e.g., using the length before appending).
  • Fix: Use the length of the slice after the append operation to index the new element, or more reliably, use slice[len(slice)-1].
    mySlice = append(mySlice, newValue)
    // Incorrect: Assuming the new element is at index len(mySlice) if len(mySlice) was used before append
    // fmt.Println(mySlice[len(mySlice)]) // This would panic
    
    // Correct way to access the newly appended element
    fmt.Println(mySlice[len(mySlice)-1])
    
    This correctly targets the last element, which is the one most recently added.

5. Nil Slice vs. Empty Slice Confusion

  • Diagnosis: Differentiate between a nil slice and an empty slice ([]T{}).
  • Cause: A nil slice has a length and capacity of 0. Accessing an index on a nil slice will panic, just like an empty slice. Sometimes, code might check if mySlice == nil but then proceed to access mySlice[0] without checking len(mySlice).
  • Fix: Always check len(slice) to determine if a slice is safe to access, regardless of whether it’s nil or an explicitly initialized empty slice.
    var nilSlice []int // nilSlice has len 0, cap 0
    emptySlice := []int{} // emptySlice has len 0, cap 0
    
    // Incorrectly assuming nil check is sufficient
    if nilSlice == nil {
        // fmt.Println(nilSlice[0]) // This will panic
    }
    
    // Correct check for both nil and empty slices
    if len(nilSlice) > 0 {
        fmt.Println(nilSlice[0])
    } else {
        fmt.Println("Slice is nil or empty.")
    }
    
    The len() function correctly reports 0 for both nil and empty slices, making it the universal check for index safety.

6. Incorrect Index for Map Values (Less Common but Possible)

  • Diagnosis: If you are iterating over a map and using the map’s values to index into a slice or array, check the map’s value.
  • Cause: The value retrieved from the map might be an invalid index for the target slice/array. This can happen if the map data isn’t validated against the slice dimensions.
  • Fix: Validate the map value before using it as an index.
    dataMap := map[string]int{"item1": 5}
    mySlice := []int{10, 20, 30}
    
    index, ok := dataMap["item1"]
    if ok {
        if index < 0 || index >= len(mySlice) {
            fmt.Println("Error: Map value is an invalid index.")
        } else {
            fmt.Println(mySlice[index])
        }
    }
    
    This ensures that values from potentially untrusted sources (like maps) are safely used as indices.

After fixing these, the next error you’ll likely encounter is runtime error: invalid memory address or nil pointer dereference, as programs often have interdependencies where one fix reveals another underlying issue.

Want structured learning?

Take the full Golang course →