如何理解这个递归结果

我在编码时写了一个错误,当我解决这个问题时,我对代码的输出感到困惑,代码如下所示:


type (

    Handler func(name string) error

)


func mh(h Handler) Handler {

    return func(name string) error {

        fmt.Printf("return mh,name=%s,h=%x\n", name, h)

        return h(name)

    }

}


func main() {

    var h Handler

    h = func(name string) error {

        fmt.Printf("********************************\n")

        fmt.Printf("before func h=%x\n", h)

        h = mh(h)

        fmt.Printf("after func h=%x\n", h)

        return h(name)

    }

    fmt.Printf("main h=%x\n", h)

    h("main")

}

运行代码,输出为:


main h=486d40

********************************

before func h=486d40

after func h=486c00

return mh,name=main,h=486d40

********************************

before func h=486c00

after func h=486c00

return mh,name=main,h=486c00

return mh,name=main,h=486d40

********************************

before func h=486c00

after func h=486c00

return mh,name=main,h=486c00

return mh,name=main,h=486c00

return mh,name=main,h=486d40

.......

我不明白调用堆栈。我认为输出应该是循环“mh”。


互换的青春
浏览 104回答 2
2回答

三国纷争

要理解的关键是这一行:h = mh(h)不调用函数h。它调用mh()函数,该函数只返回一个函数值,但它不调用h()任何一个。如果将调用返回的函数值,那将调用h().所以该main()函数将一个函数值存储在 中h,然后调用h()。这h()将打印"before",然后包装 h在另一个函数中,并将结果存储在h,然后打印"after"。重要的是要知道包装函数(由 返回的值mh())是一个闭包,它存储了 的原始值h,因此将结果分配给h不会影响h包装函数内部。所以h通过调用h现在是包装函数来结束。包装函数从打印开始"return",然后调用原始的未包装函数h。原始的,h再次展开打印"before",然后它包装当前值h(这是包装函数),将其存储在中h,然后打印"after"。然后调用h,它现在是一个 2 次包装函数。它从打印开始"return",然后调用保存的h值,这是一个 1 次包装函数。1 次包装函数从"return"(再次)打印开始,然后继续原始函数,打印"before", wrapsh现在将被 3 次包装,将其存储在 中h,然后调用h(这是 3 次包装函数值) ...如此逻辑下去,存储的函数值h会越来越wrapped,被wrapped的函数总是有一个少一次wrapped previous function的保存值。随着“迭代”的继续,“包装深度”增加,因此您会看到越来越多的"return"语句被打印(因为这就是包装的作用)。

暮色呼如

罪魁祸首是这个任务:  h = mh(h)它取代了在任何返回之前/之后打印出的匿名函数中的hin的绑定。mainmh如果你更换    h = mh(h)         fmt.Printf("after func h=%x\n", h)         return h(name)和    return mh(h)(name)你会得到你期望的相互递归
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go