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 operated.
i := 42
p = &i
The *
operator denotes the pointer's underlying value.
fmt.Println(*p) // read i through the pointer p
*p = 21 // set i through the pointer p
This is known as "dereferencing" or "indirecting".
Unlike C, Go has no pointer arithmetic.
package main
import "fmt"
func main() {
i, j := 42, 2701
p := &i // point to i
fmt.Println(*p) // read i through the pointer
*p = 21 // set i through the pointer
fmt.Println(i) // see the new value of i
p = &j // point to j
*p = *p / 37 // divide j through the pointer
fmt.Println(j) // see the new value of j
}
A struct
is a collection of fields.
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
fmt.Println(Vertex{1, 2})
}
Struct fields are accessed using a dot.
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X)
}
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.
package main
import "fmt"
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
p := &v
p.X = 1e9
fmt.Println(v)
}
A struct literal denotes a newly allocated struct value by listing the values of its fields.
You can list just a subset of fields by using the Name:
syntax. (And the order of named fields is irrelevant.)
The special prefix &
returns a pointer to the struct value.
package main
import "fmt"
type Vertex struct {
X, Y int
}
var (
v1 = Vertex{1, 2} // has type Vertex
v2 = Vertex{X: 1} // Y:0 is implicit
v3 = Vertex{} // X:0 and Y:0
p = &Vertex{1, 2} // has type * Vertex
)
func main() {
fmt.Println(v1, p, v2, v3)
}
The type [n]T
is an array of n
values of type T
.
The expression
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. This seems limiting, but don't worry; Go provides a convenient way of working with arrays.
package main
import "fmt"
func main() {
var a [2]string
a[0] = "Hello"
a[1] = "World"
fmt.Println(a[0], a[1])
fmt.Println(a)
primes := [6]int{2, 3, 5, 7, 11, 13}
fmt.Println(primes)
}
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]
This selects a half-open range which includes the first element, but excludes the last one.
The following expression creates a slice which includes elements 1 through 3 of a
:
a[1:4]
package main
import "fmt"
func main() {
primes := [6]int{2, 3, 5, 7, 11, 13}
var s []int = primes[1:4]
fmt.Println(s)
}