Chapter 22: Create Slice
Create slice.
In almost every real Go program you will create slices many times per file — so understanding all the different ways to do it, together with their advantages, memory behavior and common pitfalls, is super valuable.
Today I’ll explain Create Slice like we’re sitting together with laptop open: theory first, then every realistic creation pattern with code + output + explanation + when-you-should-use-this-style.
Quick Reminder – What is a slice really?
A slice is three numbers + a hidden pointer:
|
0 1 2 3 4 5 6 7 8 9 10 |
slice = { pointer → start position in some backing array length → how many elements you can currently see (len(slice)) capacity → how many elements the backing array can hold from this starting point (cap(slice)) } |
Every time you create a slice, you’re either:
- creating a new backing array + slice header, or
- creating a slice header that points into an existing array (or another slice)
All Realistic Ways to Create a Slice (2025–2026 style)
| # | Way to create | Syntax example | Backing array? | len / cap after creation | Most common use-case | Idiomatic level |
|---|---|---|---|---|---|---|
| 1 | Slice literal | []int{1,2,3} | Yes – new | len=3, cap=3 | Small fixed lists you write by hand | ★★★★★ |
| 2 | make( []T, length ) | make([]int, 5) | Yes – new | len=5, cap=5 | When you know exact size and want zeros | ★★★★☆ |
| 3 | make( []T, len, cap ) | make([]byte, 0, 4096) | Yes – new | len=0, cap=4096 | Pre-allocate capacity (buffers, builders, append loops) | ★★★★★ |
| 4 | Slice an array | arr[:] or arr[2:7] | No – uses existing | depends on slice | Converting fixed array to dynamic slice | ★★★☆☆ |
| 5 | Slice an existing slice | bigSlice[low:high] | No – shares backing | depends on slice | Window / sub-range view | ★★★★★ |
| 6 | Slice an existing slice with cap limit | s[low:high:high] | No – shares backing | len=high-low, cap=high-low | Prevent append from touching tail elements | ★★★★☆ |
| 7 | Nil slice | var s []int or []int(nil) | No backing array | len=0, cap=0 | “no value” / optional / zero-value | ★★★★★ |
| 8 | Empty non-nil slice | []int{} or make([]int, 0) | Tiny backing array | len=0, cap=0 or small | When you want non-nil but empty | ★★★☆☆ |
Detailed Examples – Run These!
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
package main import "fmt" func printSliceInfo(name string, s []int) { if s == nil { fmt.Printf("%s: nil len=%d cap=%d\n", name, len(s), cap(s)) return } fmt.Printf("%-18s len=%-2d cap=%-2d %v\n", name+":", len(s), cap(s), s) } func main() { // ──────────────────────────────────────────────── // 1. Slice literal – most readable for small data // ──────────────────────────────────────────────── colors := []string{"red", "green", "blue"} printSliceInfo("colors literal", colors) // ──────────────────────────────────────────────── // 2 + 3. make – control length & capacity // ──────────────────────────────────────────────── zeros := make([]int, 6) // len=6, cap=6, all 0 buffer := make([]byte, 0, 8192) // len=0, cap=8192 – very common printSliceInfo("zeros (make len)", zeros) printSliceInfo("buffer (make 0,cap)", buffer) // ──────────────────────────────────────────────── // 4. From array // ──────────────────────────────────────────────── fixed := [5]int{10, 20, 30, 40, 50} fullSlice := fixed[:] // full view partial := fixed[1:4] // [20 30 40] printSliceInfo("from array full", fullSlice) printSliceInfo("from array partial", partial) // ──────────────────────────────────────────────── // 5 + 6. Slice an existing slice // ──────────────────────────────────────────────── big := []int{1,2,3,4,5,6,7,8,9,10} view := big[3:8] // [4 5 6 7 8] cap=7 safeView := big[3:8:8] // cap limited to 5 – safer printSliceInfo("normal view", view) printSliceInfo("safe view (cap limit)", safeView) // ──────────────────────────────────────────────── // 7. Nil slice vs empty non-nil // ──────────────────────────────────────────────── var nilSlice []int emptyNonNil := []int{} emptyMake := make([]int, 0) printSliceInfo("nil slice", nilSlice) printSliceInfo("empty literal", emptyNonNil) printSliceInfo("make(0)", emptyMake) } |
Typical output summary:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
colors literal len=3 cap=3 [red green blue] zeros (make len) len=6 cap=6 [0 0 0 0 0 0] buffer (make 0,cap) len=0 cap=8192 [] from array full len=5 cap=5 [10 20 30 40 50] from array partial len=3 cap=4 [20 30 40] normal view len=5 cap=7 [4 5 6 7 8] safe view (cap limit) len=5 cap=5 [4 5 6 7 8] nil slice nil len=0 cap=0 empty literal len=0 cap=0 [] make(0) len=0 cap=0 [] |
Quick Decision Guide – Which creation style to choose?
| Situation / Goal | Recommended way | Why |
|---|---|---|
| You know the exact small values right now | []int{1,2,3} | Most readable |
| You know exact size and want zero values | make([]T, size) | Clear intent |
| You will append a lot → want to avoid reallocations | make([]T, 0, estimatedCapacity) | Best performance |
| Converting fixed array to dynamic | array[:] | Zero-cost view |
| Taking a window / sub-range | s[low:high] or s[low:high:high] | Very cheap |
| Meaning “no value” / optional field | var s []T or []T(nil) | idiomatic zero value |
| Want empty but non-nil (rare) | []T{} or make([]T, 0) | Only when JSON marshaling matters |
Your Mini Practice Task Right Now
Try to create these four slices and print their len/cap:
- A nil slice of float64
- An empty non-nil slice of strings
- A pre-allocated buffer of 0 length but 1 MB capacity of bytes
- A view of the middle 4 elements from this slice: data := []int{10,20,30,40,50,60,70,80,90}
Which one has cap > len? Why?
Any part still confusing?
- What exactly happens inside append when cap is full?
- Difference between nil and len==0 in JSON / function parameters?
- 2D slices ([][]int) creation patterns?
- Or ready for append in depth next?
Keep typing & running these examples — slice creation is something you’ll do 50+ times per real project, so getting comfortable now pays off massively.
You’re doing awesome — let’s keep building! 💻🇮🇳🚀
