我遇到了一个小问题,我只有一个丑陋的解决方案。 我无法想象我是第一个,但我没有找到任何关于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
}
Func main()
触发walk()
,由于接收器t
触发walk()
,我
除了使用这个丑陋的闭包handler
作为参数之外,找不到另一种方法
到filepath.Walk()
。我希望有更多的东西
fileWalk(".", t.walk)
但这不起作用。它给出了编译错误
“方法t.walk不是表达式,必须称为”
我的闭包解决方案在这方面是正确的方法,还是有更好的选择我不知道。
PS。这是我必须使用这种闭合结构的几种情况之一
传递具有接收器的处理函数。所以,这个问题更相关
传递处理函数而不是filepath
行为。
谢谢你的建议。
答案 0 :(得分:4)
这是不可能的。
在Go中,方法主要是语法糖,接收器实际上是函数的第一个参数。 myType.walk基本上有签名func(myType, string, os.FileInfo, error) error
。当您尝试将myType.walk传递给filepath.Walk而不是t.walk时,可以看到这一点。
答案 1 :(得分:1)
虽然你提到忽略了问题的文件路径行为,但给出的例子很大程度上取决于它。
首先,要解决方法中的传递问题,请尝试定义接口。
package main
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
,而不是尝试将exec
传递给test
。
对于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())