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

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

Is it possible to bind a method at runtime?

问题

我有以下的结构:

  1. type Foo struct {
  2. Bar func(foo *Foo) bool
  3. }

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

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

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

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

  1. func (mux *ServeMux) HandleRoute(r Route) {
  2. // ...
  3. // 设置默认的匹配函数。
  4. if r.Matcher == nil {
  5. r.Matcher = mux.RouteMatcher
  6. }
  7. // ...
  8. }

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

  1. func (mux *ServeMux) Match(r *http.Request) Route {
  2. // ...
  3. if route.Matcher(&route, r) {
  4. ...
  5. }
  6. ...
  7. }

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

英文:

I have the following construct:

  1. type Foo struct {
  2. Bar func(foo *Foo) bool
  3. }

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.

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

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

  1. func (mux *ServeMux) HandleRoute(r Route) {
  2. // ...
  3. // Set default matcher.
  4. if r.Matcher == nil {
  5. r.Matcher = mux.RouteMatcher
  6. }
  7. // ...
  8. }

Then that function is used to do a matching:

  1. func (mux *ServeMux) Match(r *http.Request) Route {
  2. // ...
  3. if route.Matcher(&route, r) {
  4. ...
  5. }
  6. ...
  7. }

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

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

  1. package main
  2. import "fmt"
  3. type Foo struct{}
  4. func (f *Foo) Bar() bool {
  5. return true
  6. }
  7. func main() {
  8. var f Foo
  9. fmt.Println(f.Bar())
  10. }

输出:

  1. true

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

  1. package main
  2. import "fmt"
  3. type BarFunc func(foo *Foo) bool
  4. type Foo struct {
  5. BarFunc
  6. }
  7. func (f *Foo) Bar() bool {
  8. return f.BarFunc(f)
  9. }
  10. func UserBarFunc(foo *Foo) bool { return true }
  11. func main() {
  12. var f Foo
  13. f.BarFunc = UserBarFunc
  14. fmt.Println(f.Bar())
  15. }

输出:

  1. true
英文:

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

  1. package main
  2. import "fmt"
  3. type Foo struct{}
  4. func (f *Foo) Bar() bool {
  5. return true
  6. }
  7. func main() {
  8. var f Foo
  9. fmt.Println(f.Bar())
  10. }

Output:

  1. true

Are you trying to do something like this?

  1. package main
  2. import "fmt"
  3. type BarFunc func(foo *Foo) bool
  4. type Foo struct {
  5. BarFunc
  6. }
  7. func (f *Foo) Bar() bool {
  8. return f.BarFunc(f)
  9. }
  10. func UserBarFunc(foo *Foo) bool { return true }
  11. func main() {
  12. var f Foo
  13. f.BarFunc = UserBarFunc
  14. fmt.Println(f.Bar())
  15. }

Output:

  1. true

答案2

得分: 2

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

  1. package main
  2. import "rand"
  3. type Foo struct {}
  4. type Bar interface {
  5. Baz()
  6. }
  7. func main() {
  8. if rand.Intn(2) != 0 {
  9. // 在运行时绑定方法Baz到Foo的代码
  10. }
  11. var f Foo
  12. // 这段代码能编译通过吗?这取决于上面的if语句是否执行,而这只能在运行时知道。
  13. f.Baz()
  14. // 同样的情况。编译器无法知道f是否有一个方法Baz。
  15. var b Bar = f
  16. }

你的示例代码看起来是实现你想要的方式。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:

  1. package main
  2. import "rand"
  3. type Foo struct {}
  4. type Bar interface {
  5. Baz()
  6. }
  7. func main() {
  8. if rand.Intn(2) != 0 {
  9. // code to bind method Baz to Foo at runtime
  10. }
  11. var f Foo
  12. // Should this compile? It depends on whether or not the if
  13. // statement above ran, which can only be known at runtime.
  14. f.Baz()
  15. // Same here. The compiler can't know whether or not f has
  16. // a method Baz.
  17. var b Bar = f
  18. }

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:

确定