Skip to content

Instantly share code, notes, and snippets.

@erikcorry
Created March 30, 2021 15:25
Show Gist options
  • Save erikcorry/2adac1929e74e56e9cc9f2e929558640 to your computer and use it in GitHub Desktop.
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.
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