4

我遇到了一个小问题,对此我只有一些丑陋的解决方案。我无法想象我是第一个,但我还没有找到任何关于 SO 的线索。

在下面的(故意简化的)示例中,我想在walk函数上有一个接收器,它是我的filepath.WalkFunc.

package main

import (
    "fmt"
    "os"
    "path/filepath"
)

type myType bool

func main() {
    var t myType = true

    // would have loved to do something as:
    // _ = filepath.Walk(".", t.walk) 

    // that does not work, use a closure instead    
    handler := func(path string, info os.FileInfo, err error) error {return t.walk(path, info, err)}
    _ = filepath.Walk(".", handler)
}

func (t myType) walk(path string, info os.FileInfo, err error) error {

    // do some heavy stuff on t and paths
    fmt.Println(t, path)

    return err
}

Funcmain()触发器walk(),并且由于接收器tto walk(),我找不到其他方法,只能使用这个丑陋的闭包handler作为filepath.Walk(). 我本来希望有更多类似的东西, fileWalk(".", t.walk)但这不起作用。它给出了编译错误“方法 t.walk 不是表达式,必须调用”

在这方面,我的关闭解决方案是正确的方法,还是我不知道有更好的选择。

PS。这是我必须使用此闭包构造来传递具有接收器的处理程序函数的几种情况之一。因此,这个问题更多地与传递处理函数有关,而不是与filepath行为有关。

谢谢你的建议。

4

2 回答 2

4

这是不可能的。

在 Go 中,方法大多是语法糖,接收者实际上是函数的第一个参数。myType.walk 基本上有签名func(myType, string, os.FileInfo, error) error。当您尝试将 myType.walk 传递给 filepath.Walk 而不是 t.walk 时,您会看到这一点。

于 2012-10-26T12:46:21.563 回答
1

虽然您提到忽略问题的文件路径行为,但给出的示例在很大程度上取决于它。

首先,要解决传入方法的问题,请尝试定义接口。

包主

import (
    "fmt"
)

type Foo interface {
    Bar(a string)
}

type myFoo bool

func (b myFoo) Bar(a string) {
    fmt.Println(b, a)
}

func exec(f Foo) {
    f.Bar("hello from exec")
}

func main() {
    var test myFoo
    exec(test)
}

因此,在上面,您实际上将定义一个描述什么功能的接口,然后完全传入,而不是尝试传递test.Bar给。exectest

对于 filepath.Walk,它没有定义接口,而是需要一个函数类型作为参数。在这种情况下,您需要使用 func 类型包装您的方法filepath.WalkFunc

如果您发现自己需要这样做很多(未经测试),您可能可以为您的类型添加一个额外的方法

func (t myType) handlerFunc() filepath.WalkFunc {
    return func(path string, info os.FileInfo, err error) error {
        return t.walk(path, info, err)
    }
}

然后打电话filepath.Walk(".", t.handlerFunc())

于 2012-10-26T14:08:46.717 回答