2017-08-16 50 views
0

我在围棋来到后关闭的例子在这里: https://gobyexample.com/closures去重新封闭的可变

它给围棋封闭作用域的一个非常直接的例子。我改变了我是如何从“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是否变量 'i' 的在intSeq()不获取重新分配每次nextInt()在主()被调用?

回答

0

在做i := *new(int)没有意义。该行称:

  1. 分配一个新的int
  2. 创建一个指向它
  3. 取消引用指针
  4. 分配值i

这无异于i := 0var int i不同,但是在创建,取消引用和放弃永远不会使用的指针的过程中还有额外的步骤。

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

+0

同意。尽管我想对此表示赞赏,但这在技术上不是问题的答案,所以我必须坚持积极的评论;) – RayfenWindspear

2

不,它不。这是关闭的要点。您正在初始化一个整型变量并将其存储在堆中供intSeq()函数返回的函数使用。没有变量初始化在nextInt()功能发生

你会得到一个使用从0开始每次调用intSeq()

编辑一个新的序列计数器一个新功能:添加到这个,这是一个糟糕的方式得到当前的行为。更好的方法是创建一个新的sequence类型,其中包含方法nextInt() int。例如:

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()) 
} 
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创建一个新的)。

我希望澄清一下。