在函数内部定义函数

问题描述:

When defining a inner function which utilizes the variables of outer scope, should I pass the variables to the inner function as parameters?

In my example, generate and generate2 both give me same result, is there a reason I should choose any one of them?

The code picks key 1 to generate combinations with key 3,4,5, then picks key 2 to generate combinations with key 3,4,5.

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello, playground")

    src := map[int][]string{
        1: []string{"1", "11", "111"},
        2: []string{"2", "22"},
        3: []string{"3"},
        4: []string{"4"},
        5: []string{"5", "55"},
    }

    result2 := generate2(src)

    fmt.Println(result2)

    result := generate(src)

    fmt.Println(result)

}

func generate(src map[int][]string) []string {
    var combo []string
    var add = func(f []string) {
        for _, v := range f {

            for _, p := range src[3] {
                for _, q := range src[4] {
                    for _, r := range src[5] {
                        combo = append(combo, v+p+q+r)
                    }
                }
            }

        }
    }

    add(src[1])
    add(src[2])
    return combo
}

func generate2(src map[int][]string) []string {
    var combo []string
    var add = func(f []string, combo []string, src map[int][]string) []string {
        for _, v := range f {
            for _, p := range src[3] {
                for _, q := range src[4] {
                    for _, r := range src[5] {
                        combo = append(combo, v+p+q+r)
                    }
                }
            }
        }
        return combo
    }

    combo = add(src[1], combo, src)
    combo = add(src[2], combo, src)
    return combo
}

在定义使用外部作用域变量的内部函数时,应将变量作为参数传递给内部函数 ? p>

在我的示例中,generate和generate2都给我相同的结果,是否有理由我应该选择其中之一? p>

代码 选择键1生成键3,4,5的组合, t选择键2生成键3,4,5的组合。 p>

 包main 
 
import  (
“ fmt” 
)
 
func main(){
 fmt.Println(“ H​​ello,Playground”)
 
 src:= map [int] []字符串{
 1:[]  string {“ 1”,“ 11”,“ 111”},
 2:[] string {“ 2”,“ 22”},
 3:[] string {“ 3”},
 4:[  ] string {“ 4”},
 5:[] string {“ 5”,“ 55”},
} 
 
 result2:= generate2(src)
 
 fmt.Println(result2)\  n 
结果:= generate(src)
 
 fmt.Println(结果)
 
} 
 
func generate(src map [int] [] string)[] string {
 var combo [] 字符串
 var add = func(f [] string){
f 或_,v:=范围f {
 
表示_,p:=范围src [3] {
表示_,q:=范围src [4] {
表示_,r:=范围src [  5] {
 combo = append(combo,v + p + q + r)
} 
} 
} 
 
} 
} 
 
 add(src [1])
 add  (src [2])
返回组合
} 
 
func generate2(src map [int] [] string)[] string {
 var combo [] string 
 var add = func(f [] string  ,组合[] string,src map [int] [] string)[] string {
表示_,v:=范围f {
表示_,p:= src [3] {
表示_,q  := range src [4] {
 _,r:= range src [5] {
 combo = append(combo,v + p + q + r)
} 
} 
} 
}  
 return combo 
} 
 
 combo = add(src [1],combo,src)
 combo = add(src [2],combo,src)
 return combo 
} 
  代码>  pre> 
  div>

When defining a inner function which utilizes the variables of outer scope, should I pass the variables to the inner function as parameters?

It depends on what you want to achieve.

What you call "a function inside a function" is actually called "a closure" (and some people call it "lambda").

Closures capture variables from the outer lexical scope, referenced in its body. In Go, this capturing is done "by reference" or "by name" which basically means each time a closure is called it will "see" current values of the variables it closes over, not the values these variables had at the time the closure was created—observe that the program:

package main

import (
    "fmt"
)

func main() {
    i := 42

    fn := func() {
      fmt.Println(i)
    }

    fn()
    i = 12
    fn()
}

would output

42
12

Conversely, when you pass values as arguments to calls to a closure, each call will see exactly the values passed to it.

I hope you now see that what strategy to pick largely depends on what you want.

Conceptually, you may think of a closure as being an instance of an ad-hoc anonymous struct data type, the fields of which are pointers to the variables the closure closes over, and each call to that closure being analogous to calling some (anonymous, sole) method provided by that type (actually, that's what the compiler usually does behind your back to implement a closure). Such "method" may have arguments, and whether it should have them, and what should go to the type's fields and what should be that method's arguments can be judged using the usual approach you employ with regular types.

In this context, there is no functional difference between the two functions. As you noticed, local functions have access to local variables without explicitly passing them. In your example you might prefer to use generate1 for easier reading.