Created
March 30, 2021 15:25
-
-
Save erikcorry/2adac1929e74e56e9cc9f2e929558640 to your computer and use it in GitHub Desktop.
Go passes maps and some interfaces by reference, most other things by value.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
func main() { | |
myMap := map[string]bool{} | |
populateMap(myMap) | |
println(len(myMap)) // Prints 1 because maps are passed by reference. | |
mySlice := []int{} | |
populateSlice(mySlice) | |
println(len(mySlice)) // Prints 0 because slices are passed by value. | |
mySlice2 := []int{0} | |
writeThroughSlice(mySlice2) | |
println(mySlice2[0]) // Prints 1 because slices sometimes alias each other. | |
myArray := [1000_000]int{} | |
writeToArray(myArray) | |
println(myArray[999999]) // Prints 0 because arrays are passed by value, regardless of length. | |
myStruct := MyStruct{} | |
writeToStruct(myStruct) | |
println(myStruct.x) // Prints 0 because structs are passed by value. | |
myStruct2 := MyStruct{} | |
writeThroughInterface(myStruct2) | |
println(myStruct2.x) // Prints 0 because this interface is for non-pointer methods. | |
myStruct3 := MyStruct{} | |
writeThroughPointerInterface(&myStruct3) | |
println(myStruct3.x) // Prints 1 because this interface is for pointer methods. | |
} | |
func populateMap(m map[string]bool) { | |
m["hello"] = true // Modfies the map from the point of view of caller. | |
} | |
func populateSlice(s []int) { | |
s = append(s, 42) // Doesn't modify the slice the caller had. | |
} | |
func writeThroughSlice(s []int) { | |
s[0] = 1 // May modify the slice the caller had because they have the same backing. | |
} | |
func writeToArray(a [1000_000]int) { | |
a[999999] = 1 // We were given a copy of the million entry array so this has no effect. | |
} | |
func writeToStruct(s MyStruct) { | |
s.x = 1 // Doesn't modify the struct - we have a copy. | |
} | |
func writeThroughInterface(s SetXer) { | |
s.SetX(1) // Doesn't modify the struct - we are calling via a non-pointer method. | |
} | |
func writeThroughPointerInterface(s SetXViaPointerI) { | |
s.SetXViaPointer(1) // Modifies the struct - we are calling via a pointer method. | |
} | |
type MyStruct struct { // implements SetXer, SetXViaPointerI | |
x int | |
y int | |
} | |
// Causes MyStruct to implement SetXer. | |
func (s MyStruct) SetX(value int) { | |
s.x = value | |
} | |
// Causes MyStruct to implement SetXBiaPointerI. | |
func (s *MyStruct) SetXViaPointer(value int) { | |
s.x = value | |
} | |
// Implicitly implemented by MyStruct. | |
type SetXer interface { | |
SetX(value int) | |
} | |
// Implicitly implemented by MyStruct. | |
type SetXViaPointerI interface { | |
SetXViaPointer(value int) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment