Go - Slice of Slices



In Go, a slice of slices is a list of lists(2D slice), where each element of the outer slice itself a slice. It is used to represent matrices, grids, or other multi-dimensional data structures.

For Example: Imagine a table(spreadsheet), The outer slice represents rows and each inner slice represents columns in that row. When we need dynamic sizes (rows can have different lengths). We can use it to store grid-like data (matrices, tables, game boards).

Here's how you can create and work with a slice of slices in Go −

Declaring a Slice of Slices

It allows you to create a 2D structure (like a grid or table) where each row is itself a slice.

var matrix [][]int

How to Declare:

// Method 1: Literal initialization
grid := [][]int{
   {4, 5, 6},       // First row (slice)
   {7, 8},          // Second row (can be different length)
}
// Method 2: Using make()
rows := 3
matrix := make([][]int, rows)      // Outer slice
for i := range matrix {
   matrix[i] = make([]int, 2)     // Each row has 2 columns (can vary)
}

Initializing a Slice of Slices

It involves creating a two-dimensional data structure in Go, where each inner slice represents a row. This allows flexible storage and manipulation of tabular data, where sizes of rows can be adjusted individual if needed. To initialize a slice of slices, we can use the make function:

matrix := make([][]int, 3) // Create an outer slice with 3 inner slices
for i := range matrix {
    matrix[i] = make([]int, 4) // Each inner slice has 4 elements
}

Accessing and Modifying Elements

It involves using indexing to navigate rows and columns and allows you to retrieve or update specific elements within the 2D structure.

matrix[0][0] = 4
matrix[1][2] = 6
fmt.Println(matrix)

Appending to a Slice of Slices

Appending to a slice of slices means adding a new row or extending an existing row. We can add a new slice as a row or increase the elements in a particular row using 'append()'

newRow := []int{7, 8, 9, 10}
matrix = append(matrix, newRow)
fmt.Println(matrix)

Iterating Over a Slice of Slices

Here, we can use nested loops of range over the elements. The outer loop access each row (slice) and the inner loop access elements within that row. Rows can vary in length making it flexible for grids and tables.

for i, row := range matrix {
    for j, val := range row {
        fmt.Printf("matrix[%d][%d] = %d\n", i, j, val)
    }
}

Here is a complete example to understand this concept −

Example: Creating a 2D Slice

In this Go program, we create a 2x4 matrix (2 rows, 4 columns) using a slice of slices, fills it with numbers 1 to 6, and prints each row.

package main
import "fmt"
func main() {
   // Initialize a 2x4 slice of slices
   matrix := make([][]int, 2)
   for i := range matrix {
       matrix[i] = make([]int, 4)
   }
   matrix[0][0] = 4
   matrix[0][1] = 5
   matrix[0][2] = 6
   matrix[0][3] = 0
   matrix[1][0] = 7
   matrix[1][1] = 8
   matrix[1][2] = 9
   matrix[1][3] = 10
   for _, row := range matrix {
       fmt.Println(row)
   }
}

Following is the output to the above program −

[4 5 6 0]
[7 8 9 10]

Jagged Slices

Slices of slices in Go can be "jagged", means each inner slice can have a different length.

jagged := [][]int{
    {4, 5},
    {6, 7, 8},
    {9},
}
fmt.Println(jagged)

Example

In this example, we define a jagged 2D slice in Go, where each row (inner slice) can have a different number of elements. A nested "range" loop is used through each row. So that it prints its index, length, and elements of different lengths.

package main
import "fmt"
func main() {
   // Declare a jagged slice of slices
   jagged := [][]int{
    {4, 5},
    {6, 7, 8},
    {9},
    }  
   fmt.Println(jagged)  
   for i, innerSlice := range jagged {
      fmt.Printf("Slice %d: %v (Length: %d)\n", i, innerSlice, len(innerSlice))
   }
}

Following is the output to the above program −

[[4 5] [6 7 8] [9]]
Slice 0: [4 5] (Length: 2)
Slice 1: [6 7 8] (Length: 3)
Slice 2: [9] (Length: 1)

A slice in go language is a variable length array which means that values can be added and deleted from it as per convenience. Here, we will create a slice of slices using two examples, slice of slices means that many slices are contained in a slice. In the first example, we will demonstrate the creation of slice of slices in two ways, firstly we will initiate the slice of slices with some values and in the second way an empty slice of slices will be created in which values will be appended later on. In the second example, an empty slice of slices will be created using the make function and then values will be appended in it to get the output.

Syntax

func make ([] type, size, capacity)

The make function in go language is used to create an array/map that accepts the type of variable to be created, its size and capacity as arguments.

funcappend(slice, element_1, element_2…, element_N) []T

The append function is used to add values to an array slice. It takes a number of arguments. The first argument is the array to which we wish to add the values followed by the values to add. The function then returns the final slice of the array containing all the values.

Algorithm

  • Create a package main and declare the fmt(format package) package in the program where main produces executable codes and fmt helps in formatting input and output.

  • Create a main function and in that function create a slice of slices of type integer

  • Initialize the slice with some values and print the slice of slices on the console using Println function where ln means new line

  • Then, create an empty slice of slices of type integer and append values in the slice of slices using append method which is a built-in function in Golang

  • Then, print the empty_slice on the console similarly like we did in last steps

Example 1

In this example, we will create a main and in that main we will create a slice of slices and add values in the slice of slices, and in the second way we will create an empty slice and append values in the empty slice using append method. In this way we will demonstrate how to create slice of slices.

package main
import "fmt"
//Main function to execute the program
func main() {
   slice_of_slices := [][]int{
      []int{10, 20, 30},
      []int{40, 50, 60},
      []int{70, 80, 90},
   }
   // Print the slice of slices
   fmt.Println("The slice of slices is:")
   fmt.Println(slice_of_slices)
   // Create an empty slice of slices and append slices to it
   empty_slice := [][]int{}
   empty_slice = append(empty_slice, []int{1, 10, 2})
   empty_slice = append(empty_slice, []int{3, 4, 5})
   empty_slice = append(empty_slice, []int{6, 7, 8})
   // Print the empty slice of slices with appended slices
   fmt.Println(empty_slice)
}

Following is the output to the above program −

The slice of slices is:
[[10 20 30] [40 50 60] [70 80 90]]
[[1 10 2] [3 4 5] [6 7 8]]

Example 2

Here, In the main function an empty slice of slices will be created in which values will be added through the use of different slices with the append method. The output will be the slice of slices printed on the console using the fmt package.

package main
import "fmt"
func main() {
   // Create an empty slice of slices
   slice_of_slices := make([][]int, 0)
   slice1 := []int{10, 20, 30}
   slice2 := []int{40, 50, 60}
   slice3 := []int{70, 80, 90}
   slice_of_slices = append(slice_of_slices, slice1)
   slice_of_slices = append(slice_of_slices, slice2)
   slice_of_slices = append(slice_of_slices, slice3)
   // Print the slice of slices on the console
   fmt.Println("The slice of slices is:")
   fmt.Println(slice_of_slices)
}
The slice of slices is:
[[10 20 30] [40 50 60] [70 80 90]]
Advertisements