douzi1350 2016-09-23 06:48
浏览 204
已采纳

使用Golang中的结构体将方法转换为函数

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?

Thanks:)

  • 写回答

1条回答 默认 最新

  • dousou3027 2016-09-23 07:02
    关注

    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

    T.Mv
    

    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(7)
    T.Mv(t, 7)
    (T).Mv(t, 7)
    f1 := T.Mv; f1(t, 7)
    f2 := (T).Mv; f2(t, 7)
    

    Similarly, the expression

    (*T).Mp 
    

    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

    (*T).Mv
    

    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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程
  • ¥20 模型在y分布之外的数据上预测能力不好如何解决
  • ¥15 processing提取音乐节奏
  • ¥15 gg加速器加速游戏时,提示不是x86架构
  • ¥15 python按要求编写程序
  • ¥15 Python输入字符串转化为列表排序具体见图,严格按照输入
  • ¥20 XP系统在重新启动后进不去桌面,一直黑屏。
  • ¥15 opencv图像处理,需要四个处理结果图