2016-09-23 06:48


I read some strange codes which convert a method to a function whose first argument is a pointer to this method's struct.

I write an example to demonstrate it:

package main

import "fmt"

type fooS struct{}

func (s *fooS) fooF(fooArg interface{}) {
    fmt.Println("fooF: ", fooArg)

type wowS struct {
    callback func(s *fooS, fooArg interface{})

func main() {
    wow := new(wowS)
    wow.callback = (*fooS).fooF // strange
    wow.callback(nil, 123)

Golang Playground Link

The example's syntax is strange but has no error.

Can any one tell me how these codes work or give me an official document about them?


  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答


  • dousou3027 dousou3027 5年前

    Method expressions:

    If M is in the method set of type T, T.M is a function that is callable as a regular function with the same arguments as M prefixed by an additional argument that is the receiver of the method.

    MethodExpr    = ReceiverType "." MethodName .
    ReceiverType  = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .

    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

    The expression


    yields a function equivalent to Mv but with an explicit receiver as its first argument; it has signature

    func(tv T, a int) int

    That function may be called normally with an explicit receiver, so these five invocations are equivalent:

    T.Mv(t, 7)
    (T).Mv(t, 7)
    f1 := T.Mv; f1(t, 7)
    f2 := (T).Mv; f2(t, 7)

    Similarly, the expression


    yields a function value representing Mp with signature

    func(tp *T, f float32) float32

    For a method with a value receiver, one can derive a function with an explicit pointer receiver, so


    yields a function value representing Mv with signature

    func(tv *T, a int) int

    Such a function indirects through the receiver to create a value to pass as the receiver to the underlying method; the method does not overwrite the value whose address is passed in the function call.

    The final case, a value-receiver function for a pointer-receiver method, is illegal because pointer-receiver methods are not in the method set of the value type.

    Function values derived from methods are called with function call syntax; the receiver is provided as the first argument to the call. That is, given f := T.Mv, f is invoked as f(t, 7) not t.f(7). To construct a function that binds the receiver, use a function literal or method value.

    It is legal to derive a function value from a method of an interface type. The resulting function takes an explicit receiver of that interface type.

    And see:
    Go - difference between parameter and receiver
    Is there a performance penalty for passing "this" by value in Go methods?
    differences between pointer and value slice in for-range loop

    点赞 评论 复制链接分享