// Week 1 – Values, pointers and slices in Go
// Run: go run ./w01/valueref
package main

import "fmt"

// Pass by value: the function receives a copy.
func increment(x int) {
	x = x + 1
}

// Pass by pointer: the function receives the address of the variable.
func incrementPtr(x *int) {
	*x = *x + 1
}

// In Go a swap can be done with pointers.
func swap(a, b *int) {
	*a, *b = *b, *a
}

// An array ([3]int) is a value: the whole array is copied when passed.
func incrementFirstArray(t [3]int) {
	t[0]++
}

// A slice ([]int) is a small descriptor referring to a backing array:
// the function sees the same elements.
func incrementFirstSlice(t []int) {
	t[0]++
}

func main() {
	a := 5
	increment(a)
	fmt.Println("after increment a =", a) // 5

	incrementPtr(&a)
	fmt.Println("after incrementPtr a =", a) // 6

	p := &a // p is a pointer, its value is the address of a
	fmt.Printf("address of a: %p, *p = %d\n", p, *p)

	x, y := 1, 2
	swap(&x, &y)
	fmt.Println("after swap x, y =", x, y) // 2 1

	arr := [3]int{10, 20, 30}
	incrementFirstArray(arr)
	fmt.Println("array – after incrementFirstArray:", arr) // [10 20 30]

	sl := []int{10, 20, 30}
	incrementFirstSlice(sl)
	fmt.Println("slice – after incrementFirstSlice:", sl) // [11 20 30]

	// Two slices can point to the same backing array
	other := sl
	other[1] = 0
	fmt.Println("after other[1] = 0, sl =", sl) // [11 0 30]

	// nil pointer: points nowhere
	var q *int
	fmt.Println("q == nil ?", q == nil)
	// fmt.Println(*q) // run-time error: nil pointer dereference
}
