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)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 矩阵加法的规则是两个矩阵中对应位置的数的绝对值进行加和
  • ¥15 活动选择题。最多可以参加几个项目?
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能
  • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面
  • ¥50 NT4.0系统 STOP:0X0000007B
  • ¥15 想问一下stata17中这段代码哪里有问题呀