github.com/karrick/go@v0.0.0-20170817181416-d5b0ec858b37/test/closure.go (about)

     1  // run
     2  
     3  // Copyright 2009 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Test the behavior of closures.
     8  
     9  package main
    10  
    11  import "runtime"
    12  
    13  var c = make(chan int)
    14  
    15  func check(a []int) {
    16  	for i := 0; i < len(a); i++ {
    17  		n := <-c
    18  		if n != a[i] {
    19  			println("want", a[i], "got", n, "at", i)
    20  			panic("fail")
    21  		}
    22  	}
    23  }
    24  
    25  func f() {
    26  	var i, j int
    27  
    28  	i = 1
    29  	j = 2
    30  	f := func() {
    31  		c <- i
    32  		i = 4
    33  		g := func() {
    34  			c <- i
    35  			c <- j
    36  		}
    37  		g()
    38  		c <- i
    39  	}
    40  	j = 5
    41  	f()
    42  }
    43  
    44  // Accumulator generator
    45  func accum(n int) func(int) int {
    46  	return func(i int) int {
    47  		n += i
    48  		return n
    49  	}
    50  }
    51  
    52  func g(a, b func(int) int) {
    53  	c <- a(2)
    54  	c <- b(3)
    55  	c <- a(4)
    56  	c <- b(5)
    57  }
    58  
    59  func h() {
    60  	var x8 byte = 100
    61  	var x64 int64 = 200
    62  
    63  	c <- int(x8)
    64  	c <- int(x64)
    65  	f := func(z int) {
    66  		g := func() {
    67  			c <- int(x8)
    68  			c <- int(x64)
    69  			c <- z
    70  		}
    71  		g()
    72  		c <- int(x8)
    73  		c <- int(x64)
    74  		c <- int(z)
    75  	}
    76  	x8 = 101
    77  	x64 = 201
    78  	f(500)
    79  }
    80  
    81  func newfunc() func(int) int { return func(x int) int { return x } }
    82  
    83  func main() {
    84  	runtime.GOMAXPROCS(1)
    85  	var fail bool
    86  
    87  	go f()
    88  	check([]int{1, 4, 5, 4})
    89  
    90  	a := accum(0)
    91  	b := accum(1)
    92  	go g(a, b)
    93  	check([]int{2, 4, 6, 9})
    94  
    95  	go h()
    96  	check([]int{100, 200, 101, 201, 500, 101, 201, 500})
    97  
    98  	memstats := new(runtime.MemStats)
    99  	runtime.ReadMemStats(memstats)
   100  	n0 := memstats.Mallocs
   101  
   102  	x, y := newfunc(), newfunc()
   103  	if x(1) != 1 || y(2) != 2 {
   104  		println("newfunc returned broken funcs")
   105  		fail = true
   106  	}
   107  
   108  	runtime.ReadMemStats(memstats)
   109  	if n0 != memstats.Mallocs {
   110  		println("newfunc allocated unexpectedly")
   111  		fail = true
   112  	}
   113  
   114  	ff(1)
   115  
   116  	if fail {
   117  		panic("fail")
   118  	}
   119  }
   120  
   121  func ff(x int) {
   122  	call(func() {
   123  		_ = x
   124  	})
   125  }
   126  
   127  func call(func()) {
   128  }