An array has a fixed length, and that length is part of the type. That means [3]int and [4]int are different types, even though both contain integers.
Arrays are useful when the size is truly fixed, such as RGB values, small lookup tables, test fixtures, or low-level data. In everyday application code, slices are more common because they can grow.
| Expression | Meaning |
|---|---|
[3]int | Array of exactly three integers. |
[...]string{"a", "b"} | Array length inferred from values. |
len(scores) | Number of array elements. |
package main
import "fmt"
func main() {
scores := [3]int{80, 90, 100}
fmt.Println(scores[0])
fmt.Println(len(scores))
scores[1] = 95
fmt.Println(scores)
}
A slice is a flexible view over an underlying array. Slices are the normal choice for ordered lists because they can grow with append.
A slice has a length and a capacity. Length is the number of visible elements. Capacity is how many elements can fit before Golang must allocate a larger backing array.
package main
import "fmt"
func main() {
languages := []string{"Golang", "Java"}
languages = append(languages, "TypeScript")
for index, language := range languages {
fmt.Printf("%d. %s\n", index+1, language)
}
}
Use len to get the number of visible elements and cap to get the capacity of the backing array. Capacity matters most when you care about allocations or performance.
You can create a slice with make and provide length and capacity. This is useful when you know roughly how many items will be added.
users := make([]string, 0, 3)
users = append(users, "Asha")
users = append(users, "Ravi")
fmt.Println(len(users)) // 2
fmt.Println(cap(users)) // 3
The slice expression items[start:end] creates a slice from an existing array or slice. The start index is included and the end index is excluded.
Remember that slices can share the same backing array. If you modify one slice, another slice that views the same backing array may observe the change. Use copy when you need an independent slice.
numbers := []int{10, 20, 30, 40, 50}
middle := numbers[1:4]
fmt.Println(middle) // [20 30 40]
middle[0] = 99
fmt.Println(numbers) // [10 99 30 40 50]
Use copy when one slice should not share changes with another. This is common when returning internal data from a package, storing request input, or preventing accidental mutation.
The destination slice must already have enough length for the copied elements. copy returns the number of elements copied.
source := []string{"go", "typescript", "java"}
clone := make([]string, len(source))
copied := copy(clone, source)
clone[0] = "golang"
fmt.Println(source[0]) // go
fmt.Println(copied) // 3
A map stores key-value pairs. The key type must be comparable, such as string, int, bool, or a struct made from comparable fields.
Maps are useful for lookup tables, counters, caches, grouping, and indexes. The zero value of a map is nil, and writing to a nil map causes a panic, so initialize maps with a literal or make before assigning values.
package main
import "fmt"
func main() {
views := map[string]int{
"golang": 1500,
"typescript": 2200,
}
if total, ok := views["golang"]; ok {
fmt.Println("Golang views:", total)
}
views["golang"]++
delete(views, "typescript")
}
When reading a map, use the comma-ok form if you need to know whether the key exists. A missing key returns the zero value of the value type, which may be ambiguous.
For example, a map value of 0 may mean the key exists with zero views, or it may mean the key is missing. The ok value tells the difference.
scores := map[string]int{
"Asha": 0,
}
score, ok := scores["Asha"]
if ok {
fmt.Println("score exists:", score)
}
missingScore, ok := scores["Ravi"]
fmt.Println(missingScore, ok) // 0 false
Choose the collection based on the behavior you need. Use arrays for fixed-size values, slices for ordered growing lists, and maps for fast lookup by key.
For many backend APIs, slices are used for lists in JSON responses, and maps are used for indexes, counters, caches, feature flags, and lookup tables.
| Collection | Best Use | Can Grow |
|---|---|---|
| Array | Fixed-size values | No |
| Slice | Ordered lists and JSON arrays | Yes |
| Map | Fast lookup by key | Yes |
append returns the updated slice and may allocate a new backing array.
copy when independence matters.
Explore 500+ free tutorials across 20+ languages and frameworks.