Skip to content

Instantly share code, notes, and snippets.

@samertm
Created July 19, 2015 02:51
Show Gist options
  • Save samertm/59928bc579d8589c840b to your computer and use it in GitHub Desktop.
Save samertm/59928bc579d8589c840b to your computer and use it in GitHub Desktop.
Surprising behavior for value types with pointer methods.
package main
import "fmt"
type T struct {
Thing string
}
func (t *T) Set(thing string) {
t.Thing = thing
}
func SetT(t *T, thing string) {
t.Thing = thing
}
type Setter interface {
Set(thing string)
}
func SetSetter(s Setter, thing string) {
s.Set(thing)
}
func main() {
// Surprising behavior for value types with pointer methods.
//
// Everyone knows that you can trivially call a method defined on a value
// (e.g. 'func (t T) SomeFunc() {}; pointerT := &T{}; t.SomeFunc()'). This
// is simple to explain conceptually: the pointer is copied and used in the
// body of the method as a value type.
//
// But did you know that you can call pointer methods on value types?
var t T = T{Thing: "HI"} // t is of type T (a value, not a pointer).
fmt.Println(t) // Prints "{HI}"
// SetT takes a pointer of T. We must give it t's address (&t) because t
// is a value type, not a pointer type. 'SetT(t, "BRO")' would error.
SetT(&t, "BRO")
fmt.Println(t) // Prints "{BRO}"
// Set is a method defined on the *pointer* T. Even though t is a value,
// not a pointer, THIS IS STILL VALID AND IT MODIFIED t. WTF??
t.Set("YO")
fmt.Println(t) // Prints "{YO}"
// MORAL OF THE STORY: No matter whether you define a variable as a value
// or a pointer, you can still call pointer methods on it and modify your
// variable.
//
// This basically turns all types into reference types (like Java) when
// methods are called on them.
// BONUS: For interfaces, pointer types have all of the methods defined on
// pointers and values for a type, but value types only have the methods
// defined on values for a type.
// SetSetter(t, "HELLO") // -> error! T does not implement Setter (Set method has pointer receiver)
SetSetter(&t, "HI THERE") // Totally fine.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment