Pointers
Go has pointers. A pointer holds the memory address of a value.
The type *T
is a pointer to a T
value. Its zero value is nil
var p *int
The &
operator generates a pointer to its operand.
1 | i := 42 |
The *
operator denotes the pointer’s underlying value.
1 | fmt.Println(*p) // read i through the pointer p |
This is known as “dereferencing” or “indirecting”.
1 | func main() { |
Structs
A struct
is a collection of fields.
Struct fields are accessed with a dot.
Struct fields can be accessed through a struct pointer.
To access the field X of a struct when we have the struct pointer p we could write (*p).X
. However, that notation is cumbersome, so the language permits us instead to write just p.X
, without the explicit dereference.
1 | type Vertex struct { |
Arrays
The type [n]T
is an array of n
values of type T
.
var a [10]int
declares a variable a
as an array of ten integers. An array’s length is part of its type, so arrays cannot be resized.
1 | func main() { |
Slices
Check this: Go Slices: usage and internals
An array has a fixed size. A slice, on the other hand, is a dynamically-sized, flexible view into the elements of an array. In practice, slices are much more common than arrays.
The type []T
is a slice with elements of type T
.
A slice is formed by specifying two indices, a low and high bound, separated by a colon:
a[low : high]
(include low, exclude high)
1 | func main() { |
Slices are like references to arrays
A slice does not store any data, it just describes a section of an underlying array.
Changing the elements of a slice modifies the corresponding elements of its underlying array.
Other slices that share the same underlying array will see those changes.
1 | func main() { |
A slice literal is like an array literal without the length.
Array literal: [3]bool{true, true, false}
And this creates the same array as above, then builds a slice that references it:
[]bool{true, true, false}
1 | func main() { |
Slice defaults
When slicing, you may omit the high or low bounds to use their defaults instead.
The default is zero for the low bound and the length of the slice for the high bound.
var a [10]int
1 | // Same below |
A slice has both a length and a capacity
The length of a slice is the number of elements it contains.
The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice.
The length and capacity of a slice s
can be obtained using the expressions len(s)
and cap(s)
.
1 | func main() { |
Nil slices
The zero value of a slice is nil
.
A nil
slice has a length and capacity of 0 and has no underlying array.
1 | func main() { |
Creating slice with make
To create dynamically-sized arrays: create slices with the built-in make
function.
The make
function allocates a zeroed array and returns a slice that refers to that array:
a := make([]int, 5) // len(a) = 5
To specify a capacity, pass a third argument to make
.
1 | b := make([]int, 0, 5) // len(b) = 0, cap(b) = 5 |
1 | func main() { |
Slice can contain any type, including other slices.
1 | func main() { |
Append to a slice
func appends(s []T, vs ...T) []T
: The resulting value of append is a slice containing all the elements of the original slice plus the provided values.
If the backing array of s is too small to fit all the given values a bigger array will be allocated. The returned slice will point to the newly allocated array.
1 | func main() { |