我在编码时写了一个错误,当我解决问题时,我对代码的输出感到困惑,代码如下:
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”。
答案 0 :(得分:0)
罪魁祸首是这个任务:
h = mh(h)
它从匿名函数替换了h
中main
在mh
返回之前或之后打印的绑定。
如果替换
h = mh(h)
fmt.Printf("after func h=%x\n", h)
return h(name)
使用
return mh(h)(name)
您将获得期望的相互递归
答案 1 :(得分:0)
要理解的关键是这一行:
h = mh(h)
不调用h
函数。它调用mh()
函数,该函数仅返回一个函数值,但也不调用h()
。如果将调用返回的函数值,则将调用h()
。
因此main()
函数将函数值存储在h
中,然后调用h()
。
此h()
打印"before"
,然后在另一个函数中包装 h
,并将结果存储在h
中,然后打印{{1 }}。重要的是要知道包装函数(由"after"
返回的值)是一个闭包,并且它存储了mh()
的原始值,因此将结果分配给h
不会影响h
位于包装函数中。
因此h
通过调用h
(现在是包装函数)结束。包装的函数首先打印h
,然后调用原始的未包装的"return"
。
原始的未包装的h
再次打印h
,然后包装"before"
的当前值(这是包装的函数),将其存储在h
中,然后打印h
。
然后调用"after"
,它现在是2倍包装函数。首先打印h
,然后调用保存的"return"
值,该值是1次环绕函数。 1次换行功能首先打印h
,然后继续进行原始操作,先打印"return"
,换行"before"
,现在将进行3次换行,存储它在h
中,然后调用h
(这是3倍的包装函数值)...
此逻辑继续,存储在h
中的函数值将越来越多地被包装,并且包装的函数始终具有比先前的包装函数少一倍的保存值。
随着“迭代”的继续,“包装深度”增加,因此您将看到越来越多的h
语句被打印出来(这就是包装的作用)。