DEV Community

go-dev
go-dev

Posted on

Pass by Mystery: Unraveling Value Changes in Go

#go

In Golang, data falls into two main categories:

Value Types: These are independent data units that are copied when passed around. Examples include:
Basic types: integers (int, uint, etc.), floating-point numbers (float32, float64), booleans (bool), strings, runes (single characters).
Arrays: Fixed-size collections of the same type (e.g., [5]int). Changes to array elements within functions create copies, not modifying the original array.

Reference Types: These hold a reference (memory address) to the actual data, allowing functions to modify the original data. Examples include:
Slices: Dynamically sized, resizable views into underlying arrays. Changes to slice elements within functions directly modify the original data.
Maps: Unordered collections of key-value pairs. Changes to map values within functions modify the original map.
Pointers: Variables that store memory addresses of other variables, allowing indirect access and manipulation.

Here is a sample program to showcase these properties:

package main

import "fmt"

func main() {
    // Declare and initialize variables
    fmt.Println("-------original------") // Print a header for initial values

    // Array - Fixed size collection of elements of the same type
    var arr [2]int // Declare an array of size 2 to hold integers
    arr[0] = 1      // Initialize the first element with value 1
    arr[1] = 2      // Initialize the second element with value 2

    // Slice - Dynamically sized view into an underlying array
    slice := []int{1, 2} // Create a slice with initial values 1 and 2

    // Map - Unordered collection of key-value pairs
    m := map[int]int{1: 1, 2: 2} // Create a map with key-value pairs (1:1, 2:2)

    // Print the initial state of array, slice, and map
    fmt.Printf("array = %v, slice = %v, map = %v\n", arr, slice, m)

    // Call function f to potentially modify the passed variables
    f(arr, slice, m)  // Pass the array (copy), slice (reference), and map (reference)

    fmt.Println() // Print an empty line for separation
    fmt.Println("-------post update------") // Print a header for modified values

    // Print the state of array, slice, and map after function calls
    fmt.Printf("array = %v, slice = %v, map = %v\n", arr, slice, m)
}

// Function f takes array, slice, and map (references)
func f(arr [2]int, slice []int, m map[int]int) {
    // Modify elements within the array (array is passed by value, changes won't affect original)
    arr[0] = 2 // Change the first element of the array copy to 2

    // Modify elements within the slice (slice is passed by reference, changes will affect original)
    slice[0] = 2 // Change the first element of the slice to 2

    // Modify elements within the map (map is passed by reference, changes will affect original)
    m[1] = 2 // Change the value associated with key 1 in the map to 2

    // Call function f2 to potentially modify the passed variables further
    f2(arr, slice, m)
}

// Function f2 takes array, slice, and map (references)
func f2(arr [2]int, slice []int, m map[int]int) {
    // Modify elements within the array (array is passed by value, changes won't affect original)
    arr[1] = 3 // Change the second element of the array copy to 3

    // Modify elements within the slice (slice is passed by reference, changes will affect original)
    slice[1] = 3 // Change the second element of the slice to 3

    // Modify elements within the map (map is passed by reference, changes will affect original)
    m[2] = 3 // Change the value associated with key 2 (or create a new key-value pair) in the map to 3
}
Enter fullscreen mode Exit fullscreen mode

Output

-------original------
array = [1 2], slice = [1 2], map = map[1:1 2:2]

-------post update------
array = [1 2], slice = [2 3], map = map[1:2 2:3]
Enter fullscreen mode Exit fullscreen mode

Top comments (0)