Golang remove from slice: delete element by index and while iterating

Golang remove from slice and delete element from slice golang: by index with order, swap-pop without order, first element, and safe patterns while iterating.

Published

Updated

Read time 3 min read

Reviewed byDeepak Prasad

Golang remove from slice: delete element by index and while iterating

This article is about golang remove from slice and delete element from slice golang: you know which index (or which predicate) must disappear while the rest stays. That covers golang remove element from slice, golang remove item from slice, go remove element from slice, and remove element from slice golang. If you instead need golang remove duplicates from slice or a golang unique slice, that is a different problem; use the companion post on removing duplicates from a slice so order-preserving dedupe and map-based uniqueness stay in one place.

Examples were run with a recent Go toolchain on Linux. Validate indices in real code; these snippets focus on the mechanics.


Remove one element by index (order preserved)

To golang delete from slice at index i and keep relative order, splice with append: everything before i, then everything after i. This matches the usual go remove item from slice answer when “shift down” behavior is required.

go
package main

import (
	"fmt"
	"slices"
)

func removeOrdered[T comparable](s []T, i int) []T {
	return append(s[:i], s[i+1:]...)
}

func main() {
	before := []int{1, 2, 3, 4, 5}
	i := 2
	after := removeOrdered(slices.Clone(before), i)
	fmt.Println("before:", before)
	fmt.Println("after: ", after)
}
Output

Run prints before unchanged and after as [1 2 4 5].


Remove one element by index (order not preserved)

When you only need golang remove from slice quickly and order does not matter, copy the last element over index i, zero the tail slot if you store pointers, then truncate. This is the classic swap-and-pop pattern.

go
package main

import (
	"fmt"
	"slices"
)

func removeUnordered[T comparable](s []T, i int) []T {
	s[i] = s[len(s)-1]
	var zero T
	s[len(s)-1] = zero
	return s[:len(s)-1]
}

func main() {
	s := []int{1, 2, 3, 4, 5}
	i := 2
	out := removeUnordered(s, i)
	fmt.Println(out)
}
Output

Run shows four elements; order differs from the ordered-delete version because the last value moved into the removed slot.


Golang remove first element from slice

Deleting only the head is delete at index 0:

go
package main

import "fmt"

func removeFirst[T comparable](s []T) []T {
	if len(s) == 0 {
		return s
	}
	return s[1:]
}

func main() {
	fmt.Println(removeFirst([]int{9, 8, 7}))
}
Output

Run prints [8 7].


Golang remove element from slice while iterating

Avoid mutating the slice length while doing a simple forward for range over the same backing array for arbitrary removals. A safe idiom is a write index (filter in place) when you only drop values that match a predicate:

go
package main

import "fmt"

func dropEvens(nums []int) []int {
	n := 0
	for _, v := range nums {
		if v%2 != 0 {
			nums[n] = v
			n++
		}
	}
	return nums[:n]
}

func main() {
	s := []int{1, 2, 3, 4, 5, 6}
	fmt.Println(dropEvens(s))
}
Output

Run prints [1 3 5]. For deleting by collected indices, sort indices descending and remove each, or build a new slice without the unwanted positions.


Summary

Golang remove element from slice at a known index is either ordered splicing with append or an unordered swap followed by truncation; golang remove first element from slice is the i == 0 case of the same idea. For golang remove element from slice while iterating, prefer filtering with a write cursor or a new slice instead of deleting under a naive forward iterator. Bounds-check i before slicing so you do not panic. When the task is deduplication or golang unique slice behavior rather than deleting one slot, follow golang remove duplicates from slice instead of stretching this page.


References


Frequently Asked Questions

1. Does append(slice[:i], slice[i+1:]...) allocate a new array?

It may reuse the backing array of the original slice if capacity allows; you still get a new slice header with updated length. Treat the result as a new logical slice and avoid holding stale references to the old length if other code expects the backing store unchanged.

2. Why can removing during range be wrong?

Skipping forward while shrinking shifts indices under you. Build a new slice, use a filter pattern with a write cursor, or remove by index from the end of the index list first.

3. When is the swap-with-last trick unsafe?

When you rely on stable ordering, when the slice contains pointers or mutexes where position matters, or when concurrent readers expect the old element at i until you publish the shorter slice.

4. What happens on an out-of-range index?

Go panics when slicing with an invalid index. Check i >= 0 && i < len(s) before calling removal helpers in production code.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise …