在运行时绑定一个方法是否可能?

huangapple go评论88阅读模式
英文:

Is it possible to bind a method at runtime?

问题

我有以下的结构:

type Foo struct {
    Bar func(foo *Foo) bool
}

因为Bar实际上不是一个方法,它接受Foo作为参数(类似于Python中的绑定方法的self)。然而,如果有一种简单的方法,我会将它绑定到结构体作为一个方法。我怀疑我可以使用反射来实现,但我想保持它简单。有没有一种将函数绑定到结构体的技巧?你会怎么做?

编辑:我将添加一个具体的例子来说明我在做什么。

type Route struct {
    Matcher func(route *Route, r *http.Request) bool
}

Route接受一个自定义的Matcher函数。如果未设置,则在注册路由时设置默认的匹配函数:

func (mux *ServeMux) HandleRoute(r Route) {
    // ...

    // 设置默认的匹配函数。
    if r.Matcher == nil {
        r.Matcher = mux.RouteMatcher
    }
    
    // ...
}

然后,该函数用于进行匹配:

func (mux *ServeMux) Match(r *http.Request) Route {
    // ...

    if route.Matcher(&route, r) {
        ...
    }

    ...
}

该函数并未绑定到路由上。我的问题是,这种设置自定义可调用对象的方式是否合理/符合惯例,或者是否有一种将函数“绑定”到结构体作为方法的技巧。

英文:

I have the following construct:

type Foo struct {
    Bar func(foo *Foo) bool
}

Because Bar is not really a method, it accepts Foo as parameter (like self in Python's bound methods). I'd however bind it to the struct as a method if there was an easy way. I suspect I could using reflection, but I want to keep it trivial. Is there a trick to bind a function to a struct? How would you do it?

Edit: I'll add a concrete example of what I'm doing.

type Route struct {
    Matcher func(route *Route, r *http.Request) bool
}

Route accepts a custom Matcher function. If not set, a default matcher function is set when the route is registered:

func (mux *ServeMux) HandleRoute(r Route) {
    // ...

    // Set default matcher.
    if r.Matcher == nil {
        r.Matcher = mux.RouteMatcher
    }
    
    // ...
}

Then that function is used to do a matching:

func (mux *ServeMux) Match(r *http.Request) Route {
    // ...

    if route.Matcher(&route, r) {
        ...
    }

    ...
}

The function is not bound to the route. My question is if this is a reasonable/idiomatic way to set a custom callable, or if there is a trick to make the function "bound" to the struct as a method.

答案1

得分: 2

你没有解释你想要实现什么。这个有什么问题吗?

package main

import "fmt"

type Foo struct{}

func (f *Foo) Bar() bool {
    return true
}

func main() {
    var f Foo
    fmt.Println(f.Bar())
}

输出:

true

你想要做类似这样的事情吗?

package main

import "fmt"

type BarFunc func(foo *Foo) bool

type Foo struct {
    BarFunc
}

func (f *Foo) Bar() bool {
    return f.BarFunc(f)
}

func UserBarFunc(foo *Foo) bool { return true }

func main() {
    var f Foo
    f.BarFunc = UserBarFunc
    fmt.Println(f.Bar())
}

输出:

true
英文:

You don't explain what you are trying to accomplish. What is wrong with this?

package main

import "fmt"

type Foo struct{}

func (f *Foo) Bar() bool {
	return true
}

func main() {
	var f Foo
	fmt.Println(f.Bar())
}

Output:

true

Are you trying to do something like this?

package main

import "fmt"

type BarFunc func(foo *Foo) bool

type Foo struct {
	BarFunc
}

func (f *Foo) Bar() bool {
	return f.BarFunc(f)
}

func UserBarFunc(foo *Foo) bool { return true }

func main() {
	var f Foo
	f.BarFunc = UserBarFunc
	fmt.Println(f.Bar())
}

Output:

true

答案2

得分: 2

在运行时绑定新方法是不可能的。编译器需要在编译时知道类型有哪些方法。考虑以下代码:

package main

import "rand"

type Foo struct {}

type Bar interface {
    Baz()
}

func main() {
    if rand.Intn(2) != 0 {
        // 在运行时绑定方法Baz到Foo的代码
    }

    var f Foo

    // 这段代码能编译通过吗?这取决于上面的if语句是否执行,而这只能在运行时知道。
    f.Baz()

    // 同样的情况。编译器无法知道f是否有一个方法Baz。
    var b Bar = f
}

你的示例代码看起来是实现你想要的方式。PeterSO的答案提供了另一种方式,使函数看起来更像是一个普通的方法。

英文:

It's not possible to bind a new method at runtime. The compiler needs to know what methods a type has at compile time. Consider this code:

package main

import "rand"

type Foo struct {}

type Bar interface {
    Baz()
}

func main() {
    if rand.Intn(2) != 0 {
        // code to bind method Baz to Foo at runtime
    }

    var f Foo

    // Should this compile? It depends on whether or not the if
    // statement above ran, which can only be known at runtime.
    f.Baz()

    // Same here. The compiler can't know whether or not f has
    // a method Baz.
    var b Bar = f
}

Your example code looks like a reasonable way to do what you want. PeterSO's answer presents another way to do it that makes the function look more like a regular method.

答案3

得分: 0

你可以创建一个带有所需名称(Bar)的辅助方法,在运行时选择并调用所需的函数,这样怎么样?

英文:

How about you create a helper method with the desired name (Bar) that chooses and calls the desired function at runtime?

huangapple
  • 本文由 发表于 2011年8月14日 23:06:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/7057579.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定