Slices in Go are descriptors over a backing array: length, capacity, and a pointer. Golang slice delete and golang remove from slice almost always mean changing the length (and sometimes capacity) by reslicing or by copy and append patterns. Searchers ask for golang remove last element from slice, golang slice remove last element, go remove last element from slice, remove last element from slice golang, golang remove first element from slice, golang remove element from slice, golang remove item from slice, and golang delete from slice; those map to a small set of idioms plus slices.Delete on modern Go.
Tested with Go 1.24 on Linux.
Drop the first or last element (prefix and suffix)
Golang remove first element from slice: use s = s[1:] when len(s) > 0. To drop the first n elements, use s = s[n:] after validating 0 <= n <= len(s).
Golang remove last element from slice and golang slice remove last element: use s = s[:len(s)-1] when len(s) > 0. To drop the last n elements, s = s[:len(s)-n] with the same bound check.
Run the program: you should see [2 3 4 5], then [2 3 4], then [4] after dropping one from the front, one from the end, then two from the front.
package main
import "fmt"
func main() {
s := []int{1, 2, 3, 4, 5}
if len(s) > 0 {
s = s[1:]
}
fmt.Println(s)
if len(s) > 0 {
s = s[:len(s)-1]
}
fmt.Println(s)
n := 2
if n <= len(s) {
s = s[n:]
}
fmt.Println(s)
}If n can be out of range, clamp or return early instead of reslicing (bad indices panic).
Remove one element by index
Keep order (typical golang remove element from slice)
Shift everything after the index forward with copy, then shorten:
package main
import "fmt"
func removeOrdered(s []int, i int) []int {
if i < 0 || i >= len(s) {
return s
}
copy(s[i:], s[i+1:])
return s[:len(s)-1]
}
func main() {
s := []int{1, 2, 3, 4, 5}
s = removeOrdered(s, 2)
fmt.Println(s)
}You should see [1 2 4 5]. Time cost is O(len(s) - i) because of copy.
Do not keep order (O(1) delete at index)
Swap the victim with the last element, then truncate:
package main
import "fmt"
func removeSwap(s []int, i int) []int {
if i < 0 || i >= len(s) {
return s
}
s[i] = s[len(s)-1]
return s[:len(s)-1]
}
func main() {
s := []int{1, 2, 3, 4, 5}
s = removeSwap(s, 1)
fmt.Println(s)
}Output order among the survivors is not the original order; this is O(1).
Go 1.21+: slices.Delete for golang delete from slice
The slices package provides slices.Delete, which removes s[i:j] and returns the new slice header (same idea as append(s[:i], s[j:]...)).
package main
import (
"fmt"
"slices"
)
func main() {
s := []int{1, 2, 3, 4, 5}
s = slices.Delete(s, 2, 3)
fmt.Println(s)
s = slices.Delete(s, 0, 2)
fmt.Println(s)
}You should see [1 2 4 5] then [4 5]. Requires Go 1.21 or newer.
Remove several elements starting at an index
With copy, move the block after index+n down to index, then shorten by n:
package main
import "fmt"
func removeRange(s []int, index, n int) []int {
if n <= 0 || index < 0 || index > len(s) || index+n > len(s) {
return s
}
copy(s[index:], s[index+n:])
return s[:len(s)-n]
}
func main() {
s := []int{1, 2, 3, 4, 5}
s = removeRange(s, 1, 2)
fmt.Println(s)
}You should see [1 4 5]. On Go 1.21+, slices.Delete(s, index, index+n) is equivalent and often clearer.
Random index (example only)
To golang remove item from slice at a pseudorandom index for demos, use math/rand and rand.Intn(len(s)) after checking len(s) > 0. Never call rand.Intn(0)—that panics.
Summary
Golang remove last element from slice and golang remove first element from slice use s[:len(s)-1] and s[1:] with length checks. Golang remove element from slice at index i while keeping order uses copy(s[i:], s[i+1:]) and s[:len(s)-1], or slices.Delete(s, i, i+1) on Go 1.21+. Golang delete from slice for a span is copy plus truncate or slices.Delete(s, i, j). Swap-and-truncate is O(1) at the cost of order. Clearer copy can help when you already get impressions, but traffic is not guaranteed to jump from one refresh alone.

