我有一个递归函数,我想只执行一个语句只对函数的最外层调用。我如何实现此功能?
func fact(n int) int {
if n == 0 {
return 1
}
fact := n * fact(n-1)
if outer_most{
fmt.Printf(strconv.Itoa(n))
}
return fact
}
func main() {
fact(4)
}
这应该只打印4
要回答问题本身:如果由于某种原因你真的想要运行仅用于最外层func调用并且不想更改api的东西,Golang就有一个运行时库。你可以这样做:
package main
import (
"fmt"
"runtime"
"strconv"
)
func outer_most() bool {
pc:=make([]uintptr,2)
runtime.Callers(2,pc) //skip: 1 - runtime.Caller, 2 - outer_most itself
return runtime.FuncForPC(pc[0])!=runtime.FuncForPC(pc[1]) // test if the caller of the caller is the same func, otherwise it is the outermost
}
func fact(n int) int {
if n == 0 {
return 1
}
fact := n * fact(n-1)
if outer_most() {
fmt.Printf(strconv.Itoa(n))
}
return fact
}
func main() {
fact(4)
}
操场:qazxsw poi这不是一个好习惯,但最直接地解决问题。
注意:使用全局变量很可能会导致故障。每次调用func时都需要设置它,如果有可靠性,则会涉及数据争用。
如果你对每个递归调用(可能是无数次)分配额外的bool参数这一事实感到不自然,你可以查看@Adrian的答案或将其包装为bool的方法。
你可以传递像https://play.golang.org/p/ro1ZOn6yIR7这样的东西,在每次通话时都会增加。例如:
depth
如果这确实是你的用例,你做得更好:
func fact(depth int, n int) int {
if n == 0 {
return 1
}
fact := n * fact(depth + 1, n-1)
if depth == 0 {
fmt.Println(fact) // I assume you meant to print fact here.
}
return fact
}
func main() {
fact(0, 4)
}
回答编辑过的问题:
您可以再次使用下面的第二个模式:
func fact(n int) int {
if n == 0 {
return 1
}
return n * fact(n-1)
}
func main() {
fmt.Println(fact(4))
}
同样,您可以使用闭包或帮助函数来清理它。
原始答案:
尝试使用全局变量:
func fact(n int, outerMost bool) int {
if n == 0 {
return 1
}
fact := n * fact(n-1, false)
if outerMost {
fmt.Printf(strconv.Itoa(n))
}
return fact
}
func main() {
fact(4, true)
}
还有其他方法可以实现这一目标。例如,您也可以使用与闭包相似的技术。或者向var outerMost bool = true
func fact(n int) int {
if outerMost {
fmt.Printf(strconv.Itoa(n))
outerMost = false
}
if n == 0 {
return 1
}
return n * fact(n-1)
}
func main() {
fact(4)
}
添加另一个参数:
fact
一个简单的匿名函数可能是最干净的,因为它不添加参数,使外部调用者的API复杂化只是为了实现内部逻辑。
func fact(n int, outerMost bool) int {
if outerMost {
fmt.Printf(strconv.Itoa(n))
outerMost = false
}
if n == 0 {
return 1
}
return n * fact(n-1, outerMost)
}
func main() {
fact(4, true)
}
这实现了相同的功能,但调用者不必知道传递与其无关的额外bool或int值。这里有完整的例子:func fact(n int) int {
var facto func(n int) int
facto = func(n int) int {
if n == 0 {
return 1
}
fact := n * facto(n-1)
return fact
}
n = facto(n)
fmt.Printf("%d", n)
return n
}