SoFunction
Updated on 2025-03-06

One article teaches you how to quickly learn Go's slice and array data types

What is an array

An array is a collection of elements of the same type. For example, a collection of integers 5, 8, 9, 79, 76 forms an array. There is no allow mixing of different types of values ​​in Go, for example, arrays containing both strings and integers.

Declare an array

Arrays belong to type. Represents the number of elements in the array and represents the type of each element. The number of elements is also part of the type (we will discuss this in more detail later.[n]TnTn

There are different ways to declare an array. Let's take a look one by one.

package main

import (  
    "fmt"
)


func main() {  
    var a [3]int //int array with length 3
    (a)
}

var a [3]int Declares an array of integers of length 3. All elements in the array will automatically assign zero values ​​of the array type. In this case it is an array of integers, so all elements are assigned to the zero value of int. Run the above program to printa a 0

[0 0 0]

The index of the array starts from , and ends at . Let's assign some values ​​to the above array. 0 length - 1.

package main

import (  
    "fmt"
)


func main() {  
    var a [3]int //int array with length 3
    a[0] = 12 // array index starts at 0
    a[1] = 78
    a[2] = 50
    (a)
}

a[0] Assigns the value to the first element of the array. The program will print

[12 78 50]

Let's create the same array using the phrase syntax declaration.

package main 

import (  
    "fmt"
)

func main() {
    // short hand declaration to create array
    a := [3]int{12, 78, 50} 
    (a)
}

The above program will print the same output:

[12 78 50]

During a phrase syntax declaration, it is not necessary to assign values ​​to all elements in the array.

package main

import (  
    "fmt"
)

func main() {  
    a := [3]int{12} 
    (a)
}

In the above program, line 8 declares an array of length 3, but only provides one value. The remaining 2 elements will be automatically specified. This program will printa := [3]int{12} 12 0

[12 0 0]

You can even ignore the length of the array in the declaration and replace it with and let the compiler find the length for you. This is done in the following program....

package main

import (  
    "fmt"
)

func main() {
    // ... makes the compiler determine the length
    a := [...]int{12, 78, 50} 
    (a)
}

The size of the array is part of the type. Therefore and are different types. Therefore, it is impossible to resize the array.

package main

func main() {  
    a := [3]int{5, 78, 8}
    var b [5]int
    b = a 
    //not possible since [3]int and [5]int are distinct types
}

In line 6 of the program above, we try to assign a variable of type to an unsubmitted type variable, so the compiler will print the following error:

./:6:7: cannot use a (type [3]int) as type [5]int in assignment

Array is a value type

Arrays in Go are value types, not reference types. This means that when they are assigned to new variables, a copy of the original array will be assigned to the new variable. If a new variable is changed, it will not be reflected in the original array.

package main

import "fmt"

func main() {  
    a := [...]string{"USA", "China", "India", "Germany", "France"}
    b := a // a copy of a is assigned to b
    b[0] = "Singapore"
    ("a is ", a)
    ("b is ", b) 
}

The above code will print out the following:

a is [USA China India Germany France]  
b is [Singapore China India Germany France]

Likewise, when arrays are passed as arguments to functions, they are passed by values, and the original array remains the same.

package main

import "fmt"

func changeLocal(num [5]int) {  
    num[0] = 55
    ("inside function ", num)

}
func main() {  
    num := [...]int{5, 6, 7, 8, 8}
    ("before passing to function ", num)
    changeLocal(num) //num is passed by value
    ("after passing to function ", num)
}

In the 13th line program above, the array is actually passed to the function by value, so it will not change due to function calls. The program will print:

before passing to function  [5 6 7 8 8]  
inside function  [55 6 7 8 8]  
after passing to function  [5 6 7 8 8]

The length of the array

Find the length of the array by passing it as an argument to the function (len).

package main

import "fmt"

func main() {  
    a := [...]float64{67.7, 89.8, 21, 78}
    ("length of a is",len(a))

}

The above program will print:

length of a is 4

Iterate the array

Use for to iterate over elements of an array.

package main

import "fmt"

func main() {  
    a := [...]float64{67.7, 89.8, 21, 78}
    for i := 0; i < len(a); i++ { //looping from 0 to the length of the array
        ("%d th element of a is %.2f\n", i, a[i])
    }
}

The above program uses a loop to iterate over elements of an array, from index to . The program is valid and will print:

0 th element of a is 67.70  
1 th element of a is 89.80  
2 th element of a is 21.00  
3 th element of a is 78.00

Go provides a better and cleaner way to iterate over arrays by using the range form of loops. Returns the index and the value at that index. Let's rewrite the above code using scope. We will also find the sum of all the elements in the array.

package main

import "fmt"

func main() {  
    a := [...]float64{67.7, 89.8, 21, 78}
    sum := float64(0)
    for i, v := range a {//range returns both the index and value
        ("%d the element of a is %.2f\n", i, v)
        sum += v
    }
    ("\nsum of all elements of a",sum)
}

Line 8 of the above program is the scope form of the for loop. It will return the index and the value at that index. We print the values ​​and calculate the sum of all elements in the array. The output of this program is:

0 the element of a is 67.70  
1 the element of a is 89.80  
2 the element of a is 21.00  
3 the element of a is 78.00

sum of all elements of a 256.5

If you want only the value and want to ignore the index, you can do this by replacing the index with a blank identifier._

for _, v := range a { //ignores index  
}

The for loop above ignores the index. Similarly, this value can be ignored.

Multidimensional array

So far, the arrays we have created are all single-dimensional. Multidimensional arrays can be created.

package main

import (  
    "fmt"
)

func printarray(a [3][2]string) {  
    for _, v1 := range a {
        for _, v2 := range v1 {
            ("%s ", v2)
        }
        ("\n")
    }
}

func main() {  
    a := [3][2]string{
        {"lion", "tiger"},
        {"cat", "dog"},
        {"pigeon", "peacock"}, //this comma is necessary. The compiler will complain if you omit this comma
    }
    printarray(a)
    var b [3][2]string
    b[0][0] = "apple"
    b[0][1] = "samsung"
    b[1][0] = "microsoft"
    b[1][1] = "google"
    b[2][0] = "AT&T"
    b[2][1] = "T-Mobile"
    ("\n")
    printarray(b)
}

In line 17 of the program above, a two-dimensional array of strings is declared using short-sign syntax. A comma at the end of line 20 is required. This is because the lexer automatically inserts semicolons based on simple rules. Another 2d array is declared in line 23 and adds strings one by one for each index. This is another way to initialize a 2d array.

The function in line 7 uses two for range loops to print the contents of the 2d array. The above program will print:

lion tiger  
cat dog  
pigeon peacock 

apple samsung  
microsoft google  
AT&T T-Mobile

That's it for arrays. Although arrays seem to be flexible enough, they have fixed length limitations. The length of the array cannot be increased. This is where the slice enters the screen. In fact, in Go, slices are more common than traditional arrays.

slice

Slicing is a convenient, flexible and powerful wrapper on top of an array. The slice itself does not own any data. They are just references to existing arrays.

Create slices

Slices with T-type elements are represented by the following formula[]T

package main

import (  
    "fmt"
)

func main() {  
    a := [5]int{76, 77, 78, 79, 80}
    var b []int = a[1:4] //creates a slice from a[1] to a[3]
    (b)
}

This syntax creates a slice from one index to another starting from an array. Therefore, in line 9 of the above program, create a slice representation of the array from index 1 to 3. Use this expression:a[start:end]

package main

import (  
    "fmt"
)

func main() {
    //creates and array and returns a slice reference
    c := []int{6, 7, 8} 
    (c)
}

In line 9 of the function above, create an array of 3 integers and return the slice reference stored in c.

Modify slices

The slice does not own any data. It is just a representation of the underlying array. Any modifications made to the slice will be reflected in the underlying array.

package main

import (  
    "fmt"
)

func main() {  
    darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
    dslice := darr[2:5]
    ("array before",darr)
    for i := range dslice {
        dslice[i]++
    }
    ("array after",darr) 
}

In line 9 of the above program, we create from the index 2, 3, 4 of the array. The for loop increments the values ​​in these indexes by 1. When we print the array after the for loop, we can see that the changes to the slice are reflected in the array. The output of the program is:

array before [57 89 90 82 100 78 67 69 59]  
array after [57 89 91 83 101 78 67 69 59]

When multiple slices share the same underlying array, changes made by each slice are reflected in the array.

package main

import (  
    "fmt"
)

func main() {  
    numa := [3]int{78, 79 ,80}
    nums1 := numa[:] //creates a slice which contains all elements of the array
    nums2 := numa[:]
    ("array before change 1",numa)
    nums1[0] = 100
    ("array after modification to slice nums1", numa)
    nums2[1] = 101
    ("array after modification to slice nums2", numa)
}

In line 9, the start and end values ​​are missing. The default values ​​for "start" and "end" are and , respectively. Two slices and share the same array. The output of the program is:

array before change 1 [78 79 80]  
array after modification to slice nums1 [100 79 80]  
array after modification to slice nums2 [100 101 80]

It is clear from the output that when the slices share the same array. Modifications made to slices will be reflected in the array.

Slice length and capacity

The length of the slice is the number of elements in the slice. The capacity of a slice is the number of elements in the underlying array starting from the index that creates the slice.

package main

import (  
    "fmt"
)

func main() {  
    fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    ("length of slice %d capacity %d", len(fruitslice), cap(fruitslice)) //length of fruitslice is 2 and capacity is 6
}

In the above program, it is created from indexes 1 and 2 of . Therefore, the length is 2.

The slice can be resliced ​​to its capacity. Anything beyond this value will cause the program to throw a runtime error.

package main

import (  
    "fmt"
)

func main() {  
    fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    ("length of slice %d capacity %d\n", len(fruitslice), cap(fruitslice)) //length of is 2 and capacity is 6
    fruitslice = fruitslice[:cap(fruitslice)] //re-slicing furitslice till its capacity
    ("After re-slicing length is",len(fruitslice), "and capacity is",cap(fruitslice))
}

In line 11 of the above program, it is resliced ​​to its capacity. The above program output:

length of slice 2 capacity 6  
After re-slicing length is 6 and capacity is 6

Create slices with make

To generate slices, make([]T, len, cap) can be used to create slices. []T represents the data type, len represents the slice length, and cap represents the slice capacity. The make function creates an array and returns a slice reference to it.

package main

import (  
    "fmt"
)

func main() {  
    i := make([]int, 5, 5)
    (i)
}

By default, these values ​​are cleared when creating slices with make. The above program will output .[0 0 0 0 0]

Slice append

As we already know, arrays are limited to fixed lengths and their length cannot be increased. Slices are dynamic, and new elements can be appended to slices using functions. The definition of append function is .append([]T, x...):[]T. Returns a new slice.

x ...T in the function definition indicates that the function accepts a variable number of parameters of the parameter x. These types of functions are calledVariable parameter functions

However, there is one problem that may bother you. If the slice is supported by an array, and the array itself has a fixed length, how can the slice have a dynamic length. What happens under the hood is that when a new element is appended to the slice, a new array is created. Elements of an existing array are copied to this new array and return a new slice reference to this new array. The new slice is now twice as powerful as the old slice. The following program will make things clear.

package main

import (  
    "fmt"
)

func main() {  
    cars := []string{"Ferrari", "Honda", "Ford"}
    ("cars:", cars, "has old length", len(cars), "and capacity", cap(cars)) //capacity of cars is 3
    cars = append(cars, "Toyota")
    ("cars:", cars, "has new length", len(cars), "and capacity", cap(cars)) //capacity of cars is doubled to 6
}

In the above program, the capacity is initially 3. We attach the new element to the car in line 10 and assign the returned slice to the car again. Now, the capacity of the car has doubled to become 6 vehicles. The output of the above program is:

cars: [Ferrari Honda Ford] has old length 3 and capacity 3  
cars: [Ferrari Honda Ford Toyota] has new length 4 and capacity 6

The zero value of slice type is . The length and capacity of the slice are 0. You can use the append function to append values ​​to slices.

package main

import (  
    "fmt"
)

func main() {  
    var names []string //zero value of a slice is nil
    if names == nil {
        ("slice is nil going to append")
        names = append(names, "John", "Sebastian", "Vinay")
        ("names contents:",names)
    }
}

In the above program as nil, we have appended 3 strings to . The output of the program is:

slice is nil going to append  
names contents: [John Sebastian Vinay]

You can also use operators to append a slice to another slice.

package main

import (  
    "fmt"
)

func main() {  
    veggies := []string{"potatoes","tomatoes","brinjal"}
    fruits := []string{"oranges","apples"}
    food := append(veggies, fruits...)
    ("food:",food)
}

In line 10 of the above program, by appending to the slice. The output of the program is:

fruitsveggiesfood: [potatoes tomatoes brinjal oranges apples]

Slice as function parameter

Slices can be treated as represented internally by structure types.

type slice struct {  
    Length        int
    Capacity      int
    ZerothElement *byte
}

A slice contains length, capacity, and a pointer to the zeroth element of the array. When passing a slice to a function, the pointer variable will reference the same underlying array even if it is passed by value. Therefore, when a slice is passed to a function as an argument, the changes made inside the function are also visible outside the function. Let's write a program to check it out.

package main

import (  
    "fmt"
)

func subtactOne(numbers []int) {  
    for i := range numbers {
        numbers[i] -= 2
    }

}
func main() {  
    nos := []int{8, 7, 6}
    ("slice before function call", nos)
    subtactOne(nos)                               //function modifies the slice
    ("slice after function call", nos) //modifications are visible outside
}

The function call in line 17 of the above program decrements each element of the slice by 2. These changes are visible when printing slices after function calls. If you remember, this is different from an array, where changes made to arrays inside a function are not visible outside of the function. The output of the above program is

slice before function call [8 7 6]  
slice after function call [6 5 4]

Multidimensional slices

Similar to arrays, slices can have multiple dimensions.

package main

import (  
    "fmt"
)


func main() {  
     pls := [][]string {
            {"C", "C++"},
            {"JavaScript"},
            {"Go", "Rust"},
            }
    for _, v1 := range pls {
        for _, v2 := range v1 {
            ("%s ", v2)
        }
        ("\n")
    }
}

The output result is:

C C++  
JavaScript  
Go Rust

Slices save references to the underlying array. As long as the slice is in memory, the array cannot be garbage collected. In terms of memory management, this may attract attention. Let's assume we have a very large array and we're only interested in dealing with a small portion of it. From then on, we create a slice from that array and start processing that slice. The important thing to note here is that the array will still be in memory because the slice references it.

One way to solve this problem is to use the copy function to copy the slice. This way we can use new slices and we can garbage collect the original array.copy(dst, src []T):int

package main

import (  
    "fmt"
)

func countries() []string {  
    countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}
    neededCountries := countries[:len(countries)-2]
    countriesCpy := make([]string, len(neededCountries))
    copy(countriesCpy, neededCountries) //copies neededCountries to countriesCpy
    return countriesCpy
}
func main() {  
    countriesNeeded := countries()
    (countriesNeeded)
}

In line 9 of the above program, create a slice that prohibits the last 2 elements. Line 11 of the above program is copied to the function in the next line and returns it from it. The array can now be garbage collected because it is no longer referenced.

The above is a detailed article about how to quickly learn Go slices and array data types. For more information about Go slices, please pay attention to my other related articles!