Arrays vs Slices in Go
Arrays are an important part of Data Structures and perhaps one of the most widely used. Since Go is all about performance and optimization, it provides a slight tweak to arrays. The most basic difference between both is that arrays are non-reference types while slices are reference types. When declaring each, there is also a slight change in syntax.
Array Declaration:
var array [4]int = [4]int{1, 2, 3, 4}//or you could simply use the short hand syntax for declaration
array := [4]int{1, 2, 3, 4}
Slice Declaration:
var slice []int = []int{1, 2, 3, 4}//or you could simply use the short hand syntax for declaration
slice := []int{1, 2, 3, 4}
Arrays:
Arrays in Go are values and are of fixed length. As they are values, whenever an array is assigned to a new variable, the entire array is copied instead of the reference to its address being passed. Yes, as you can imagine, working with arrays can get very expensive, especially when there are large number of elements within them. Since, whenever if the entire array is copied and assigned to a new variable, changing the new variable will not reflect the original.
originalArray := [4]int{1, 2, 3, 4}
copyArray := originalArray
copyArray[0] = 100fmt.Println(originalArray, copyArray)
//output
//[1 2 3 4] [100 2 3 4]
array variable is not a pointer to the first array element, array variable stands for the whole array
Also, an array is of type [len]T, meaning even if two arrays of same type having different length, their type’s would still be different. Henceforth, since type is determined when declaration, the array’s size cannot be changed as it will now be of different type.
arrayOfLengthFour := [4]int{1, 2, 3, 4}
arrayOfLengthSix := [6]int{1, 2, 3, 4, 5, 6}fmt.Printf("Type of arrayOfLengthFour is %T\n", arrayOfLengthFour)
//output
//Type of arrayOfLengthFour is [4]intfmt.Printf("Type of arrayOfLengthSix Array is %T\n", arrayOfLengthSix)
//output
//Type of arrayOfLengthSix Array is [6]int
Moreover, you will not be allowed to change the size of an already declared array. This also means you cannot append anything to the existing array.
Slices:
Slices are technically arrays, or rather they are built on top of arrays. A Slice is dynamic in size and internally is a reference to an array. Since they are of reference type, they are cheap to assign and can be passed to functions or new variables can have existing slices assigned to them without having to worry about the cost (as in the case of arrays).
Surprise Surprise Surprise!
As slices are references, changing values in another slice will change values in the existing slice as shown,
originalSlice := []int{1, 2, 3, 4}
copySlice := originalSlice
copySlice[0] = 100fmt.Println(originalSlice, copySlice)
//output
[100 2 3 4] [100 2 3 4]
Furthermore, unlike arrays, a slice can be resized by using the append method function.
slice := []int{1, 2, 3, 4}
slice = append(slice, 5, 6, 7, 8)fmt.Println(slice)
//output
//[1 2 3 4 5 6 7 8]
So summing up everything we get,
| # | Array | Slice |
|---------|----------------|----------------|
| Storage | As a Value | As a Reference |
| Type | Type is [len]T | Type is []T |
| Size | Fixed | Resizable |
| Usage | Not so much | Quite Often |
We could also discuss the point of having Arrays in Go in the first place. But let that be for another time.
I hope you liked the article! :)