【问题标题】:converting a method to a function with a pointer to the struct in Golang将方法转换为带有指向Golang中结构的指针的函数
【发布时间】:2016-09-23 18:36:08
【问题描述】:

我阅读了一些奇怪的代码,它们将方法转换为第一个参数是指向该方法结构的指针的函数。

我写了一个例子来演示一下:

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

例子的语法很奇怪,但没有错误。

谁能告诉我这些代码是如何工作的或给我一份关于它们的官方文件?

谢谢:)

【问题讨论】:

    标签: go


    【解决方案1】:

    Method expressions:

    如果MT类型的方法集中,T.M是一个函数 可作为常规函数调用,其参数与 M 前缀相同 通过作为方法接收者的附加参数。

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

    考虑一个结构类型T,有两个方法Mv,它的接收者是 类型T,和Mp,其接收者类型为*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
    

    表达式

    T.Mv
    

    产生一个等效于Mv的函数,但有一个明确的接收者作为 它的第一个论点;它有签名

    func(tv T, a int) int
    

    该函数可以通过显式接收器正常调用,所以 这五个调用是等价的:

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

    同样,表达式

    (*T).Mp 
    

    产生一个函数值,用签名表示 Mp

    func(tp *T, f float32) float32
    

    对于带有值接收器的方法,可以派生一个带有 显式指针接收器,所以

    (*T).Mv
    

    产生一个代表Mv的函数值,带有签名

    func(tv *T, a int) int
    

    这样的函数通过接收器间接创建一个值 作为接收者传递给底层方法;该方法不 覆盖函数调用中传递地址的值。

    最后一种情况,指针接收器的值接收器函数 方法,是非法的,因为指针接收器方法不在 值类型的方法集。

    从方法派生的函数值通过函数调用来调用 句法;接收者作为调用的第一个参数提供。 也就是说,给定f := T.Mvf 被调用为f(t, 7) 而不是t.f(7)。至 构造一个绑定接收者的函数,使用函数字面量 或方法值。

    从接口的方法派生函数值是合法的 类型。生成的函数需要一个明确的接收者 接口类型。


    请看:
    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

    【讨论】:

      猜你喜欢
      • 2020-10-21
      • 2015-01-26
      • 2015-07-13
      • 1970-01-01
      • 1970-01-01
      • 2017-01-19
      • 1970-01-01
      • 2015-01-24
      • 1970-01-01
      相关资源
      最近更新 更多