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 }