Pass slice as a function argument


In Go, the function parameters are passed by value. With respect to use slice as a function argument, that means the function will get the copies of the slice: a pointer which points to the starting address of the underlying array, accompanied by the length and capacity of the slice. Oh boy! Since you know the address of the memory which is used to store the data, you can tweak the slice now. Let’s see the following example:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func modifyValue(s []int) {
  6. s[1] = 3
  7. fmt.Printf("In modifyValue: s is %v\n", s)
  8. }
  9. func main() {
  10. s := []int{1, 2}
  11. fmt.Printf("In main, before modifyValue: s is %v\n", s)
  12. modifyValue(s)
  13. fmt.Printf("In main, after modifyValue: s is %v\n", s)
  14. }

The result is here:

  1. In main, before modifyValue: s is [1 2]
  2. In modifyValue: s is [1 3]
  3. In main, after modifyValue: s is [1 3]

You can see, after running modifyValue function, the content of slice s is changed. Although the modifyValue function just gets a copy of the memory address of slice’s underlying array, it is enough!

See another example:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func addValue(s []int) {
  6. s = append(s, 3)
  7. fmt.Printf("In addValue: s is %v\n", s)
  8. }
  9. func main() {
  10. s := []int{1, 2}
  11. fmt.Printf("In main, before addValue: s is %v\n", s)
  12. addValue(s)
  13. fmt.Printf("In main, after addValue: s is %v\n", s)
  14. }

The result is like this:

  1. In main, before addValue: s is [1 2]
  2. In addValue: s is [1 2 3]
  3. In main, after addValue: s is [1 2]

This time, the addValue function doesn’t take effect on the s slice in main function. That’s because it just manipulate the copy of the s, not the “real” s.

So if you really want the function to change the content of a slice, you can pass the address of the slice:

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func addValue(s *[]int) {
  6. *s = append(*s, 3)
  7. fmt.Printf("In addValue: s is %v\n", s)
  8. }
  9. func main() {
  10. s := []int{1, 2}
  11. fmt.Printf("In main, before addValue: s is %v\n", s)
  12. addValue(&s)
  13. fmt.Printf("In main, after addValue: s is %v\n", s)
  14. }

The result is like this:

  1. In main, before addValue: s is [1 2]
  2. In addValue: s is &[1 2 3]
  3. In main, after addValue: s is [1 2 3]