Method values

November 6, 2023

A quick reminder: In today’s live stream, I’ll be deploying a Go app to Kubernetes! I hope you’ll join me!

Today we continue the explanation of Method values. There’s nothing too surprising today. The spec mostly just confirms what should seem natural…

Method values

As in the discussion of method expressions above, consider a struct type T with two methods, Mv, whose receiver is of type T, and Mp, whose receiver is of type *T.

type T struct {
	a int
func (tv  T) Mv(a int) int         { return 0 }  // value receiver
func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver

var t T
var pt *T
func makeT() T

The expression


yields a function value of type

func(int) int

These two invocations are equivalent:

f := t.Mv; f(7)

Similarly, the expression


yields a function value of type

func(float32) float32

Again, nothing super surprising here. The main contrast with method expressions is that the receiver type is not reflected in the final function value type. That is to say, regardless of whether the method has a pointer or value receiver, the function value has the same type. In fact, regardless of the receiver’s base type, the function value is the same, given the same method signature:

type Person struct {
	/* ... */

func (p Person) Greet(name string) {}
func (p *Person) SayHi(name string) {}

type Dog string

func (d Dog) Speak(sound string) {}

var (
	p Person
	d Dog

	x = p.Greet // x, y, and z all
	y = p.SayHi // have the same type:
	z = d.Speak // func(string)

Quotes from The Go Programming Language Specification Version of August 2, 2023

Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content

Method expressions, part 2

Today I’ll continue where I left off yesterday, talking about… Method expressions … Similarly, the expression (*T).Mp yields a function value representing Mp with signature func(tp *T, f float32) float32 The key difference to notice between this example and yesterday’s is that the first argument (that of the receiver) is a pointer here, but was not a pointer in the previous example: func(tv T, a int) int // First argument of type T, not a pointer func(tp *T, f float32) float32 // First argument of type *T, a pointer For a method with a value receiver, one can derive a function with an explicit pointer receiver, so

Method values, part 2

Today we finish up the spec’s section on method values, with some very non-surprising bits: Method values … As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv. As with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value: t.

Method values

As I promised yesterday, today we’re looking at method values, a concept with some similarties to the previous concept of method expressions, but with a bit more utility. Method values If the expression x has static type T and M is in the method set of type T, x.M is called a method value. The method value x.M is a function value that is callable with the same arguments as a method call of x.