Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
仅在Golang中递归的最外层函数上运行语句_Go - Fatal编程技术网

仅在Golang中递归的最外层函数上运行语句

仅在Golang中递归的最外层函数上运行语句,go,Go,我有一个递归函数,我想要一个只为函数的最外层调用执行一些语句。如何实现此功能 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 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 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)
}
还有其他方法可以实现这一点。例如,您也可以对闭包使用类似的技术。或者将另一个参数添加到
事实

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)
}

对已编辑问题的回答

您可以再次使用下面的第二种模式:

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)
}
还有其他方法可以实现这一点。例如,您也可以对闭包使用类似的技术。或者将另一个参数添加到
事实

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)
}

您可以传递类似于
深度的内容,它在每次调用时递增。例如:

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(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))
}

一个简单的匿名函数可能是最干净的,因为它不添加参数,使得外部调用方只需实现内部逻辑的API变得复杂

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
}

这实现了相同的功能,但调用者不必知道如何传递与之无关的额外bool或int值。这里的完整示例:

一个简单的匿名函数可能是最干净的,因为它不添加参数,使外部调用方只需实现内部逻辑的API变得复杂

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
}

这实现了相同的功能,但调用者不必知道如何传递与之无关的额外bool或int值。这里的完整示例:

回答问题本身:如果出于某种原因,您确实希望运行仅用于最外层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)
}
游乐场: 这不是一个好的做法,而是最直接地解决问题

注: 使用全局变量很可能会导致故障。您需要在每次调用func时设置它,如果存在一致性,则会涉及数据竞争


如果您不同意每次递归调用都会分配额外的bool参数(这可能需要无数次),您可以查看@Adrian的答案,或者将其包装为bool方法。

来回答问题本身:如果出于某种原因,您真的想运行只用于最外层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)
}
游乐场: 这不是一个好的做法,而是最直接地解决问题

注: 使用全局变量很可能会导致故障。您需要在每次调用func时设置它,如果存在一致性,则会涉及数据竞争


如果您不同意每次递归调用都会分配额外的bool参数(这可能是无数次的),您可以查看@Adrian的答案,或者将其包装为bool方法。

我发布的问题与我需要的不同。很抱歉。请看编辑后的问题。我发布的问题与我需要的不同。很抱歉。请看编辑后的问题。