Golang: why sort takes value rather than pointer
For golang, every time a variable is passed as parameter, a new copy of the variable is created and passed to called function or method. The copy is allocated at a different memory address.This strategy is called Pass by Value, which has few side effects.
Therefore, when change struct self, we have to pass the pointer to function. For example, I would like to change the age of student:
type student struct {
name string
age int
}
func changeAge(s *student) {
s.age = 10
}
s := student{name: "Ryan Lv", age: 14}
// you need to pass a pointer to this function.
changeAge(&s)
When go through Go by Example, I found a very strange case relating to function invocation.
Counterintuitive example
package main
import "fmt"
import "sort"
func main() {
strs := []string{"c", "a", "b"}
sort.Strings(strs) // attention!
fmt.Println("Strings:", strs)
ints := []int{7, 2, 4}
sort.Ints(ints)
fmt.Println("Ints: ", ints)
s := sort.IntsAreSorted(ints)
fmt.Println("Sorted: ", s)
}
Output
$ go run sorting.go
Strings: [a b c]
Ints: [2 4 7]
Sorted: true
In this example, the counterintuitive fact is sort.Strings(strs)
took a slice as parameter, which is a value[1], sorted it, and changed it!
How does it happen?
Answer
The key is slice!
A slice is a descriptor of an array segment. It consists of a pointer to the array, the length of the segment, and its capacity (the maximum length of the segment).
When sort.Strings(sliceA), a brand new slice sliceB will be created, which also points to the array.
After the array under the hood has been sorted, I could print the sorted array through SliceA.
That’s the magic! Slice has a pointer to the real array!
Note
- At the beginning, I though of slice as “value”. Actually it’s not.