Slices in Go

Contents
Make a slice
Append grows it
Len vs cap
Slicing a slice

Make a slice

A slice is a flexible view over a backing array: it can grow, and it passes around cheaply because only a small header is copied. Build one with a literal, or with make when you know the starting length.

package main import "fmt" func main() { nums := []int{1, 2, 3} fmt.Println(nums) names := make([]string, 2) names[0] = "Ada" fmt.Println(names) }

go run main.go

[1 2 3]
[Ada ]

Notice the missing length in []int: that empty bracket pair is exactly what tells Go you want a slice and not an array. Make with two arguments sets length and capacity together; the optional third argument reserves extra room for growth without reallocation.

Append grows it

Append returns a slice with new elements added at the end, and you must store the result back because growth can move the data to a larger array. Appending is the everyday way slices grow.

package main import "fmt" func main() { nums := []int{1, 2} nums = append(nums, 3, 4) fmt.Println(nums) }

[1 2 3 4]

Forgetting the assignment back is the classic beginner bug: the append happens, but the old variable still points at the short slice. Always write nums equals append of nums to keep the grown result.

Len vs cap

Len reports how many elements the slice holds right now, while cap reports how many fit before the next growth step must allocate. Watching both explains why some appends feel free and others copy.

package main import "fmt" func main() { s := make([]int, 2, 5) fmt.Println(len(s), cap(s)) s = append(s, 1, 2, 3) fmt.Println(len(s), cap(s)) }

2 5
5 5

Capacity is a performance detail, not a limit: append past it and Go allocates a bigger array automatically. Pre sizing with make avoids repeated copying when the final size is known in advance.

Slicing a slice

Cut a new slice out of an old one with low:high bounds, where low is included and high is excluded. The result shares the same backing array, so it starts as a window rather than a copy.

package main import "fmt" func main() { nums := []int{1, 2, 3, 4, 5} mid := nums[1:4] mid[0] = 9 fmt.Println(nums) }

[1 9 3 4 5]

Sharing cuts allocations but also surprises: writing through one slice shows up in the other. Copy with the builtin copy function when the new slice must live its own life.

Next: Maps

Article author: Arthur Isaev

Related articles
Golang
Go course: zero to hero in 50 lessons
What is Go and where it runs
Install Go and check the version
Your first Go program
Modules with go mod
Variables
Constants
Types
Numbers
Strings
Conditions with if
Switch in Go
Loops with for
Arrays in Go
Slices in Go
Maps in Go
Functions in Go
Errors as values
Pointers in Go
Structs in Go
Methods in Go
Interfaces in Go
Embedding instead of inheritance
Generics in Go
Packages and imports
The go toolchain
Testing with go test
Advanced errors
defer in Go
Strings, bytes and runes
Time in Go
JSON
Files and IO
HTTP servers
HTTP clients
Context
Goroutines
Channels
select and sync
CLI: args, flags, env
Logging
Regular expressions
Sorting
Concurrency patterns
Databases with database/sql
Benchmarks and profiling
Toolchain and CI
Project layout
Capstone: wordfreq CLI
Capstone: JSON API server
Hero roadmap: the whole course on one page
Install Go on Windows 11
Install Go on Ubuntu
Install Go on Rocky Linux
Install Go on macOS
Install Go on FreeBSD
Go in Docker
Banner image

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.ru
Write to info@urn.su if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: