去重置闭包变量

时间:2017-08-16 18:08:39

标签: go closures anonymous-function

我在Go这里找到了一个闭包的例子: https://gobyexample.com/closures

它提供了一个非常简单的Go中闭包范围的例子。我改变了如何从“i:= 0”初始化为“i:= * new(int)”。

func intSeq() func() int {
    i := *new(int)
    return func() int {
        i += 1
        return i
    }
}

func main() {

    // We call `intSeq`, assigning the result (a function)
    // to `nextInt`. This function value captures its
    // own `i` value, which will be updated each time
    // we call `nextInt`.
    nextInt := intSeq()

    // See the effect of the closure by calling `nextInt`
    // a few times.
    fmt.Println(nextInt())
    fmt.Println(nextInt())
    fmt.Println(nextInt())

    // To confirm that the state is unique to that
    // particular function, create and test a new one.
    newInts := intSeq()
    fmt.Println(newInts())
}

这个输出仍然是1,2,3,1。每次调用main()中的nextInt()时,intSeq()中的变量'i'是否都不会被重新分配?

3 个答案:

答案 0 :(得分:3)

了解您如何实施intSeq

func intSeq() func() int {
    i := *new(int)
    return func() int {
        i += 1
        return i
    }
}

i的初始化超出了它返回的函数。

因此,分配新指针的唯一时间是实际调用intSeq

由于你只做了两次,这就是你得到了多少不同的指针。

这解释了为什么在你只是调用nextInt时没有重置该值(请注意,执行nextInt意味着只执行返回的函数,如下所示:

func() int {
   i += 1
   return i
}

这不会重置i的值,而是继续增加它(直到你再次调用intSeq创建一个新值)。

我希望澄清。

答案 1 :(得分:2)

不,它没有。这就是结束的关键。您正在初始化一个整数变量并将其存储在堆上,以供intSeq()函数返回的函数使用。 nextInt()函数

中没有发生变量初始化

您将获得一个新函数,该函数使用从0开始的新序列计数器,每次调用intSeq()

编辑:要添加到此,这是获取当前行为的一种不好的方法。更好的方法是创建包含方法sequence的新nextInt() int类型。 E.g:

type Sequence struct {
    counter int
}

func (s *Sequence) nextInt() int {
    s.counter++
    return s.counter
}

func main() {
    intSeq := new(Sequence)
    fmt.Println(intSeq.nextInt())
    fmt.Println(intSeq.nextInt())
    fmt.Println(intSeq.nextInt())
}

答案 2 :(得分:0)

执行i := *new(int)没有意义。那条线说:

  1. 分配新的int
  2. 创建指向它的指针
  3. 取消引用指针
  4. 将值分配给i
  5. 这与i := 0var int i没什么区别,但是在创建,解除引用和丢弃永不使用的指针的过程中还有一个额外的步骤。

    如果需要指向int的指针,请使用i := new(int)*new任何地方都是无意义的调用和代码味道。