dongni9825 2017-12-28 00:43
浏览 35
已采纳

传递要与defer一起使用的方法作为参数

We can easily pass a function as a parameter and use it with defer:

func main() {
    test(rec)
}

func test(f func(int)) {
    defer f(10)
    panic("test")
}

func rec(v int) {
    e := recover()
    fmt.Println(e)
    fmt.Println(v)
}

This works. Playground.


But what if we need to pass a method and then call recover in that method?

type MyStruct struct {
    Data string
}

func main() {
    a := &MyStruct{}
    test(a.Recover)
}

func test(f func(int)) {
    defer f(10)
    panic("test")
}

func (m *MyStruct) Recover(arg int) {
    e := recover()
    fmt.Println(e)
    fmt.Println(arg)
}

Here we get some strange behavior, which I do not fully understand. Playground.

It seems like the method get called but recover returns nil and after that there is a (another?) panic. None of the golang docs and google results has helped me to understand the reason of such behavior. What am I missing?

  • 写回答

1条回答 默认 最新

  • duankan8739 2017-12-28 01:32
    关注

    The recover() function returns nil when not called directly from the deferred function.

    A call through the method value a.Recover is not a direct call.

    Use a wrapper function that calls recover and the method:

    func main() {
        a := &MyStruct{}
        test(func(arg int) { a.Recover(arg, recover()) })
    }
    
    func test(f func(int)) {
        defer f(10)
        panic("test")
    }
    
    func (m *MyStruct) Recover(arg int, e interface{}) {
        fmt.Println(e)
        fmt.Println(arg)
    }
    

    Another option is to use a method expression, but this is probably straying from what you are trying to accomplish:

    func main() {
        a := &MyStruct{}
        test(a, (*MyStruct).Recover)
    }
    
    func test(a *MyStruct, f func(*MyStruct, int)) {
        defer f(a, 10)
        panic("test")
    }
    
    func (m *MyStruct) Recover(arg int) {
        e := recover()
        fmt.Println(e)
        fmt.Println(arg)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 求解vmware的网络模式问题 别拿AI回答
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码
  • ¥15 关于资源监视工具的e-care有知道的嘛
  • ¥35 MIMO天线稀疏阵列排布问题
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?