How Go Slices Work Under the Hood: What Makes Them Stand Out from Other Languages

1 4 25
calendar_todayschedule13 min read
— Originally published at dev.to

Hello, I'm Ganesh. I'm building git-lrc, an AI code reviewer that runs on every commit. It is free, unlimited, and source-available on Github. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product.

Slices are one of the most commonly used data structures in Go.

They appear simple on the surface, but their design is carefully engineered to provide flexibility without sacrificing performance.

In this article, we will examine how Go slices work internally and analyze the algorithm that enables them to grow dynamically while remaining efficient.

What are Slices?

Slices are dynamic arrays. It uses pointers to refer to the underlying array. Further below, we will understand more in detail.

How to create slices?

Initialize the array and create a slice from it.

For creating a slice from an array, we use [start:end] notation.

start is the starting index of the slice.

end is the ending index of the slice.

import "fmt"

func main() {
    s := [5]int{10, 20, 30, 40,50}
    fmt.Println(s)
    var s1 []int = s[1:3]
    fmt.Println(s1)
}

Output:

[10 20 30 40 50]
[20 30]

Using Structs with Slices

We can store any data type in a slice.

For example, we can store a struct in a slice.

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    people := []Person{
 {Name: "John", Age: 30},
 {Name: "Jane", Age: 25},
 }
    fmt.Println(people)
}

The output of the code will have JSON-like output inside square brackets.

Output:

[{John 30} {Jane 25}]

So, we understood how to create slices. But to understand how Go creates and how it handles slices, we have to understand the algorithm behind it. Let's see the source code of Go. link

How Slices Work Internally?

Slices will have 3 components.

  1. Pointer to the underlying array.
  2. Length of the slice.
  3. Capacity of the slice.

It is a little bit confusing, let's understand with the example below.

[10, 20, 30, 40, 50]

Slice Internal Structure

Now by above image, we can understand how slices are created internally.

Modifying Slices

When we do slicing from a new slice with a different start point, it will create a new slice with a different pointer.

If we change the pointer, then the data from the previous pointer will be lost.

To identify how it works, let's see the example below.

package main

import "fmt"

func main() {
    s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    printSlice(s)

    s = s[1:5]
    printSlice(s)

    s = s[2:]
    printSlice(s)

    s = s[:1]
    printSlice(s)
}
func printSlice(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

Here is the visual representation.

Slice Modification Internal Structure

Output:
This is actual output of the code.

gk@jarvis:~/exp/code/rd/go-exmaple$ go run main.go
len=10 cap=10 [1 2 3 4 5 6 7 8 9 10]
len=4 cap=9 [2 3 4 5]
len=2 cap=7 [4 5]
len=1 cap=7 [4]

I explained how empty data is represented in slices.

How Empty Slice is Represented?

package main

import "fmt"

func main() {
    var s []int
    fmt.Println(s, len(s), cap(s))
    if s == nil {
        fmt.Println("s is nil")
 }
}

Output:

[] 0 0
s is nil

len and cap are 0 because the slice is not initialized.

When we initialize a slice, it will have a defined length and capacity.

The underlying pointer will point to the first element of the backing array, and both the length and capacity will be set to the number of elements in that array.

Initializing a Slice

We can initialise slices with different data types.

Initializing a Slice with make

make is a predefined function in Go used to create and initialize slices, maps, and channels.

Reference variables like slices are typically initialized using the make command from Go's built-in functions.

package main

import "fmt"

func main() {
    a := make([]int, 5)
    fmt.Println(a, len(a), cap(a))

    b := make([]int, 5, 10)
    fmt.Println(b, len(b), cap(b))
}

Output:

[0 0 0 0 0] 5 5
[0 0 0 0 0] 5 10

This allows you to create a slice with a specific length and capacity.

make([]T, len, cap)

  • For a := make([]int, 5), it creates a slice of length 5 and capacity 5.
  • For b := make([]int, 5, 10), it creates a slice of length 5 and capacity 10.

Variable Declaration

You can also initialize a slice directly using a slice literal:

package main

import "fmt"

func main() {
    a := []int{1, 2, 3, 4, 5}
    fmt.Println(a, len(a), cap(a))
}

Output:

[1 2 3 4 5] 5 5

For this slice, the pointer points to the first element of the underlying array, and the length and capacity are set to the number of elements provided.
Now, we will see how to initialize 2D slices and how to append to a slice.

Initializing 2D Slices

package main

import (
    "fmt"
    "strings"
)

func main() {

    ticTacToeBoard := [][]string{
 {"_", "_", "_"},
 {"_", "_", "_"},
 {"_", "_", "_"},
 }

    ticTacToeBoard[0][0] = "X"
    ticTacToeBoard[2][2] = "O"
    fmt.Println(ticTacToeBoard)
    for i := 0; i < len(ticTacToeBoard); i++ {
        fmt.Println(strings.Join(ticTacToeBoard[i], " "))
 }
}

We are initializing a 2D slice of strings with 3 rows and 3 columns.

We can modify the values of the slice using the index variable[x][y].

Finally, we are printing the slice using a loop.

Each

1 Comment

1 vote
🔥 Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

How I Built a React Portfolio in 7 Days That Landed ₹1.2L in Freelance Work

Dharanidharan - Feb 9

Your AI Doesn't Just Write Tests. It Runs Them Too.

Kevin Martinez - May 12

Breaking the AI Data Bottleneck: How Hammerspace's AI Data Platform Eliminates Migration Nightmares

Tom Smithverified - Mar 16

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

Create a Restful API with Golang from scratch

pachecoioverified - Feb 8
chevron_left
1.1k Points30 Badges
44Posts
5Comments
3Followers
3Connections
I am tech enthusiast, IoT innovator, software developer.

Related Jobs

View all jobs →

Commenters (This Week)

14 comments
13 comments
3 comments

Contribute meaningful comments to climb the leaderboard and earn badges!