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