Go/Arrays
From charlesreid1
Go blog post: arrays, slices, and strings: https://blog.golang.org/slices
Arrays in Go
"Arrays are not often seen in Go programs because the size of an array is part of its type, which limits its expressive power."
The most common use of arrays are to store slices, which we will see in a moment.
Array size is a part of the type
An important characteristic of arrays is that their size is a part of their type.
The two variables defined here are of two distinct types:
var buffer [256]byte var buffer2 [512]byte
This is because the size of the array is allocated at initialization time. You can use the square bracket syntax to access elements of an array, buffer[0] through buffer[255]. The program crashes if you access an index outside of its range.
Array slices
The bracket notation with colons can be used to refer to a slice of an array. For example:
var buffer [256]byte ... var slice []byte = buffer[100:150]
alternatively,
slice := buffer[100:150]
Think of a slice variable as a data structure with two elements: a length, and a pointer to an element of the array.
We can also take a slice of the slice:
slice2 := slice[5:10]
Here's a shortcut to drop the first and last elements:
slice3 := slice[1:len(slice)-1]
References vs Copies
It is important to distinguish between the slice data structure, which is a small bundle that contains a reference to the underlying array data and a length, and the underlying array data itself.
if we use a slice to modify the underlying array data, those changes will be persistent across functions and scopes. But if we modify the slice variable directly, we are modifying a copy of the slice data structure, and we will discard that copy when we leave that scope.
Example modifying underlying array data
The following example modifies the underlying array data:
func AddOneToEachElement(slice []byte) {
for i := range slice {
slice[i]++
}
}
func main() {
slice := buffer[10:20]
for i := 0; i < len(slice); i++ {
slice[i] = byte(i)
}
fmt.Println("before", slice)
AddOneToEachElement(slice)
fmt.Println("after", slice)
}
Again, this requires us to think about the array slice as a data structure, which contains a pointer to an array and a length. The bundle, the data structure, is not a pointer itself!
Even though the slice (also called the "slice header") is passed by value, the header includes a pointer to elements of an array. Thus, both the original and the copy passed to the function refer to the same underlying array (slots in memory).
Example modifying copy of slice
The argument to the SubtractOneFromLength function is a slice, which in this case is a copy of the original slice data structure, containing a reference to the same underlying data.
When we modify the slice variable directly, those changes only affect the copy of the data slice, so the original slice is not affected.
func SubtractOneFromLength(slice []byte) []byte {
slice = slice[0 : len(slice)-1]
return slice
}
func main() {
fmt.Println("Before: len(slice) =", len(slice))
newSlice := SubtractOneFromLength(slice)
fmt.Println("After: len(slice) =", len(slice))
fmt.Println("After: len(newSlice) =", len(newSlice))
}
Array Slice Capacity
The capacity of an array is fixed; to make a new array with a new capacity, use the make() function.
The make function allocates space in memory for an array slice with a specified capacity.
The make function takes three arguments: the type of the slice, its initial length, and its capacity, which is the length of the array that make allocates to hold the slice data.
// Make an array slice with a length of 100 and room for 5 more slice := make([]int, 100, 15)
To double the array slice capacity:
// Original slice:
slice := make([]int, 10, 15)
fmt.Printf("len: %d, cap: %d\n", len(slice), cap(slice))
// New slice (double the capacity):
newSlice := make([]int, len(slice), 2*cap(slice))
for i := range slice {
newSlice[i] = slice[i]
}
// Replace old with new
slice = newSlice
fmt.Printf("len: %d, cap: %d\n", len(slice), cap(slice))
The above code is functional but awkward; Go provides a copy function to copy an old array into a new array, to accomplish the above in fewer lines.
newSlice := make([]int, len(slice), 2*cap(slice)) copy(newSlice, slice)
Note that copy is smart - it will copy as much as it can, but will respect the lengths of both array slices rfg.
Array Slice Insertion
This was an exercise in futility. See Go/Arrays/Array Slice Insertion
Slice Tricks
Communty Go wiki: https://github.com/golang/go/wiki/SliceTricks
Go 101 book: https://github.com/go101/go101/wiki
Flags
| Go notes on Go
Go/Strings · Go/Arrays · Go/Slices
Go/Lists · Go/Maps · Go/Stacks · Go/Queues
Go/Naming Conventions · Go/Design Patterns
Go/Timing · Go/Profiling · Go/Benchmarking
Go/Tests · Go/Travis CI · Go/Makefiles
our vim + go setup uses custom solarized colors for Golang
|