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 from deleting one known index. Use delete elements from a slice when you want slices.Delete, to drop only the first or last element, or to remove a contiguous run of indices without a filter loop.
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. Resolve i with slices.Index when you are removing by value—see find index in a slice—and assign the append result as in golang append to slice.
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)
}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.
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)
}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:
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}))
}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:
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))
}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
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.
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.
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.
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.

