Go 将方法参数传递给函数

Go 将方法参数传递给函数,go,methods,Go,Methods,我很好奇这在围棋中是否可行。我有一个具有多种方法的类型。有没有可能让一个函数接受一个方法参数,然后为类型调用它 下面是我想要的一个小例子: 主程序包 进口( “fmt” ) 输入Foo int func(f Foo)A(){ fmt.Println(“A”) } func(f Foo)B(){ fmt.Println(“B”) } func(f Foo)C(){ fmt.Println(“C”) } func main(){ 福娃 bar:=func(foo-func()){ f、 foo()

我很好奇这在围棋中是否可行。我有一个具有多种方法的类型。有没有可能让一个函数接受一个方法参数,然后为类型调用它

下面是我想要的一个小例子:

主程序包
进口(
“fmt”
)
输入Foo int
func(f Foo)A(){
fmt.Println(“A”)
}
func(f Foo)B(){
fmt.Println(“B”)
}
func(f Foo)C(){
fmt.Println(“C”)
}
func main(){
福娃
bar:=func(foo-func()){
f、 foo()
}
酒吧(A)
酒吧(B)
巴(C)
}

Go认为type
Foo
有一个名为
Foo()
的方法,而不是用传入的方法名替换它。

是的,这是可能的。您有2(3)个选项:

表达式
Foo.A
生成一个与
A
等价的函数,但其第一个参数为显式接收器;它有签名
func(f Foo)

这里的方法接收器是显式的。您只需将方法名称(及其所属类型)传递给
bar()
,调用它时,必须传递实际的接收者:
m(f)

按预期输出(在上尝试):

如果
f
是类型为
Foo
的值,则表达式
f.a
将生成类型为
func()
的函数值,其中包含隐式接收器值
f

var f Foo
bar := func(m func()) {
    m()
}
bar(f.A)
bar(f.B)
bar(f.C)
请注意,这里的方法接收器是隐式的,它与传递给
bar()
的函数值一起保存,因此调用它时没有明确指定它:
m()

输出是相同的(请在上尝试)

(为了完整性:) 与以前的解决方案相比(在性能和“安全性”方面),您可以将方法的名称作为
字符串
值传递,然后使用包以该名称调用方法。它可能是这样的:

var f Foo
bar := func(name string) {
    reflect.ValueOf(f).MethodByName(name).Call(nil)
}
bar("A")
bar("B")
bar("C")

在。

上尝试此操作。您还可以对不同的接收器使用@icza列出的“方法值”选项

package main

import "fmt"

type Foo int
type Goo int

func (f Foo) A() { fmt.Println("A") }
func (f Foo) B() { fmt.Println("B") }
func (g Goo) A() { fmt.Println("A") }

func main() {
    //Method values with receiver f
    var f Foo
    bar2 := func(m func()) { m() }
    bar2(f.A) //A
    bar2(f.B) //B
    //Method values with receivers f and g
    var g Goo
    bar2(f.A) //A
    bar2(g.A) //A
}

我玩这个游戏想要一个状态机类型的组件,它不使用map[string]func()来包含状态方法。我的代码允许使用run方法 这是一个简单的for循环,当pfunc==nil时会中断

type Foo struct {
    name string
    idx  int
}
type X func(*Foo) X

func (f *Foo) A() X {
    f.name += fmt.Sprintf(" A[%d]", f.idx)
    fmt.Println(f.name)
    if f.idx > 10 {
        fmt.Println("Foo is complete!")
        return nil
    } else {
        f.idx += 1
        return (*Foo).B
    }
}
func (f *Foo) B() X {
    f.name += fmt.Sprintf(" B[%d]", f.idx)
    fmt.Println(f.name)
    f.idx += 2
    return (*Foo).C
}
func (f *Foo) C() X {
    f.name += fmt.Sprintf(" C[%d]", f.idx)
    fmt.Println(f.name)
    f.idx += 3
    return (*Foo).A
}

func main() {
    bar := &Foo{"Ready!", 0}
    pfunc := (*Foo).A
    except := 1
    for pfunc != nil && except < 10 {
        pfunc = pfunc(bar)
        except += 1
    }
}    
类型Foo struct{
名称字符串
idx int
}
类型X func(*Foo)X
func(f*Foo)A()X{
f、 name+=fmt.Sprintf(“A[%d]”,f.idx)
fmt.Println(f.name)
如果f.idx>10{
fmt.Println(“Foo完成了!”)
归零
}否则{
f、 idx+=1
返回(*Foo).B
}
}
func(f*Foo)B()X{
f、 name+=fmt.Sprintf(“B[%d]”,f.idx)
fmt.Println(f.name)
f、 idx+=2
返回(*Foo).C
}
func(f*Foo)C()X{
f、 name+=fmt.Sprintf(“C[%d]”,f.idx)
fmt.Println(f.name)
f、 idx+=3
返回(*Foo).A
}
func main(){
条:=&Foo{“就绪!”,0}
pfunc:=(*Foo).A
除外:=1
对于pfunc!=除<10之外的零(&N){
pfunc=pfunc(巴)
除+=1外
}
}    
输出:
准备好的A[0]
准备好的A[0]B[1]
准备好的A[0]B[1]C[3]
准备好的A[0]B[1]C[3]A[6]
准备好的A[0]B[1]C[3]A[6]B[7]
准备好的A[0]B[1]C[3]A[6]B[7]C[9]
准备好的A[0]B[1]C[3]A[6]B[7]C[9]A[12]

福完成了

我不明白你在问什么。这就是你想做的吗?对于带有指针接收器的方法,您将如何执行此操作?我尝试了这个链接中显示的方法。但我不明白。因为我无法编辑以前的评论,所以添加了一条新评论。我按照说明书上的说明试了试,想出了一个好主意。但我还有一个问题。我希望打印的两个地址是相同的(Foo实例的地址
f
)@rajkamal Inside
Foo.A()
您打印的不是
f
指针,而是指针的地址
f
已经是指针,因此
&f
的类型将为
**foo
。如果将其更改为仅打印
f
的值,则会看到打印的指针相同:
package main

import "fmt"

type Foo int
type Goo int

func (f Foo) A() { fmt.Println("A") }
func (f Foo) B() { fmt.Println("B") }
func (g Goo) A() { fmt.Println("A") }

func main() {
    //Method values with receiver f
    var f Foo
    bar2 := func(m func()) { m() }
    bar2(f.A) //A
    bar2(f.B) //B
    //Method values with receivers f and g
    var g Goo
    bar2(f.A) //A
    bar2(g.A) //A
}
type Foo struct {
    name string
    idx  int
}
type X func(*Foo) X

func (f *Foo) A() X {
    f.name += fmt.Sprintf(" A[%d]", f.idx)
    fmt.Println(f.name)
    if f.idx > 10 {
        fmt.Println("Foo is complete!")
        return nil
    } else {
        f.idx += 1
        return (*Foo).B
    }
}
func (f *Foo) B() X {
    f.name += fmt.Sprintf(" B[%d]", f.idx)
    fmt.Println(f.name)
    f.idx += 2
    return (*Foo).C
}
func (f *Foo) C() X {
    f.name += fmt.Sprintf(" C[%d]", f.idx)
    fmt.Println(f.name)
    f.idx += 3
    return (*Foo).A
}

func main() {
    bar := &Foo{"Ready!", 0}
    pfunc := (*Foo).A
    except := 1
    for pfunc != nil && except < 10 {
        pfunc = pfunc(bar)
        except += 1
    }
}