Skip to content

Latest commit

 

History

History
194 lines (147 loc) · 5.44 KB

02-pointers-in-functions.md

File metadata and controls

194 lines (147 loc) · 5.44 KB

Lab: Pointers

Take me to the lab!

Help for the VSCode editor.

  1. What would be the output of the following program:

    Note: add package and import statements as needed

    func modify(numbers ...int) {
        for i := range numbers {
                numbers[i] -= 5
        }
    }
    func main() {
        arr := []int{10, 20, 30}
        fmt.Println(arr)
        modify(arr...)
        fmt.Println(arr)
    }
    • [10 20 30]
      [5 15 25]
    • [10 20 30]
      [10 20 30]
    • [10 20 30]
      [15 25 35]
    • Error
    Reveal

    [10 20 30]
    [5 15 25]

    • Create a slice of int with 3 values
    • Print it
    • Call the function modify which takes a variadic argument. The slice is passed by reference, meaning that if it modifies the values in the slice, then the caller sees the change. Slice data is always passed by reference as they behave like pointers.
    • Hence in the final Println we see that 5 has bee subtracted from all values.
  2. What would be the output of the following program:

    Note: add package and import statements as needed

    func modify(numbers [3]int) {
        for i := range numbers {
            numbers[i] -= 5
        }
    }
    func main() {
        arr := [3]int{10, 20, 30}
        fmt.Println(arr)
        modify(arr)
        fmt.Println(arr)
    }
    • [10 20 30]
      [5 15 25]
    • [10 20 30]
      [10 20 30]
    • [10 20 30]
      [15 25 35]
    • Error
    Reveal

    [10 20 30]
    [10 20 30]

    • This time an array has been declared, not a slice
    • Arrays are passed by value, therefore the modify function receives a copy of the array. The caller's array is not modified.
  3. What would be the output of the following program:

    Note: add package and import statements as needed

    func modify(numbers *[3]int) {
        for i := range numbers {
                numbers[i] -= 5
        }
    }
    func main() {
        arr := [3]int{10, 20, 30}
        fmt.Println(arr)
        modify(arr)
        fmt.Println(arr)
    }
    • [10 20 30]
      [5 15 25]
    • [10 20 30]
      [10 20 30]
    • [10 20 30]
      [15 25 35]
    • Error
    Reveal

    Error

    • The program will not compile since the modify function expects a pointer to an array of [3]int.
    • The call modify(arr) is passing the array itself, not a pointer to it.
  4. What would be the output of the following program:

    Note: add package and import statements as needed

    func modify(s *string) {
        *s = strings.ToUpper(*s)
    }
    
    func main() {
        s := "hello"
        fmt.Println(s)
        modify(&s)
        fmt.Println(s)
    }
    • hello HELLO
    • hello
      HELLO
    • HELLO hello
    • hello
    Reveal

    hello
    HELLO

    You must add strings as an import to use ToUpper

    • Initialize a string variable s with value hello, then print it.
    • The modify function takes a pointer to string, converts the value it is pointing to to upper case, then stores the conversion back in the variable being pointed to, i.e. it will modify the caller's variable.
    • main calls modify passing the address of the variable s - i.e. providing a pointer to s
    • Print the end result, which is now upper cased.
    • There is a newline in the output because Println was called twice and Println always appends a newline.
  5. What would be the output of the following program:

    Note: add package and import statements as needed

    func modify(s map[string]int) {
        s["A"] = 100
    }
    func main() {
        ascii_codes := map[string]int{}
        ascii_codes["A"] = 65
        fmt.Println(ascii_codes)
        modify(ascii_codes)
        fmt.Println(ascii_codes)
    }
    • map[A:65]
      map[A:65]
    • map[A:65]
      map[A:100]
    • [A:65]
      [A:100]
    • [A:65]
      [A:65]
    Reveal

    map[A:65]
    map[A:100]

    • When a map is printed, it is always printed like map[...] so two answers can be ruled out immediately.
    • Maps are always passed by reference in function calls, therefore modify will modify the ascii_codes map and the modification is seen in the second print.
  • Wrap up
    • Slices and maps are always passed by reference so they behave like pointers to the caller's data when used as function arguments. If a function modifies a slice or a map argument, the change will affect the caller.
    • All other types, including arrays are passed by value (a copy is made for the function to use). If you want a function to be able to modify the caller's variable, then you must use a function that takes a pointer argument like Q4, and pass the address of your variable (& operator) to the function.
    • When using or modifying the value being pointed to in the function, you use the dereference operator (*).