github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/analysis/passes/loopclosure/testdata/src/a/a.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file contains tests for the loopclosure checker. 6 7 package testdata 8 9 import ( 10 "sync" 11 12 "golang.org/x/sync/errgroup" 13 ) 14 15 var A int 16 17 func _() { 18 var s []int 19 for i, v := range s { 20 go func() { 21 println(i) // want "loop variable i captured by func literal" 22 println(v) // want "loop variable v captured by func literal" 23 }() 24 } 25 for i, v := range s { 26 defer func() { 27 println(i) // want "loop variable i captured by func literal" 28 println(v) // want "loop variable v captured by func literal" 29 }() 30 } 31 for i := range s { 32 go func() { 33 println(i) // want "loop variable i captured by func literal" 34 }() 35 } 36 for _, v := range s { 37 go func() { 38 println(v) // want "loop variable v captured by func literal" 39 }() 40 } 41 for i, v := range s { 42 go func() { 43 println(i, v) 44 }() 45 println("unfortunately, we don't catch the error above because of this statement") 46 } 47 for i, v := range s { 48 go func(i, v int) { 49 println(i, v) 50 }(i, v) 51 } 52 for i, v := range s { 53 i, v := i, v 54 go func() { 55 println(i, v) 56 }() 57 } 58 59 // iteration variable declared outside the loop 60 for A = range s { 61 go func() { 62 println(A) // want "loop variable A captured by func literal" 63 }() 64 } 65 // iteration variable declared in a different file 66 for B = range s { 67 go func() { 68 println(B) // want "loop variable B captured by func literal" 69 }() 70 } 71 // If the key of the range statement is not an identifier 72 // the code should not panic (it used to). 73 var x [2]int 74 var f int 75 for x[0], f = range s { 76 go func() { 77 _ = f // want "loop variable f captured by func literal" 78 }() 79 } 80 type T struct { 81 v int 82 } 83 for _, v := range s { 84 go func() { 85 _ = T{v: 1} 86 _ = map[int]int{v: 1} // want "loop variable v captured by func literal" 87 }() 88 } 89 90 // ordinary for-loops 91 for i := 0; i < 10; i++ { 92 go func() { 93 print(i) // want "loop variable i captured by func literal" 94 }() 95 } 96 for i, j := 0, 1; i < 100; i, j = j, i+j { 97 go func() { 98 print(j) // want "loop variable j captured by func literal" 99 }() 100 } 101 type cons struct { 102 car int 103 cdr *cons 104 } 105 var head *cons 106 for p := head; p != nil; p = p.cdr { 107 go func() { 108 print(p.car) // want "loop variable p captured by func literal" 109 }() 110 } 111 } 112 113 // Cases that rely on recursively checking for last statements. 114 func _() { 115 116 for i := range "outer" { 117 for j := range "inner" { 118 if j < 1 { 119 defer func() { 120 print(i) // want "loop variable i captured by func literal" 121 }() 122 } else if j < 2 { 123 go func() { 124 print(i) // want "loop variable i captured by func literal" 125 }() 126 } else { 127 go func() { 128 print(i) 129 }() 130 println("we don't catch the error above because of this statement") 131 } 132 } 133 } 134 135 for i := 0; i < 10; i++ { 136 for j := 0; j < 10; j++ { 137 if j < 1 { 138 switch j { 139 case 0: 140 defer func() { 141 print(i) // want "loop variable i captured by func literal" 142 }() 143 default: 144 go func() { 145 print(i) // want "loop variable i captured by func literal" 146 }() 147 } 148 } else if j < 2 { 149 var a interface{} = j 150 switch a.(type) { 151 case int: 152 defer func() { 153 print(i) // want "loop variable i captured by func literal" 154 }() 155 default: 156 go func() { 157 print(i) // want "loop variable i captured by func literal" 158 }() 159 } 160 } else { 161 ch := make(chan string) 162 select { 163 case <-ch: 164 defer func() { 165 print(i) // want "loop variable i captured by func literal" 166 }() 167 default: 168 go func() { 169 print(i) // want "loop variable i captured by func literal" 170 }() 171 } 172 } 173 } 174 } 175 } 176 177 // Group is used to test that loopclosure only matches Group.Go when Group is 178 // from the golang.org/x/sync/errgroup package. 179 type Group struct{} 180 181 func (g *Group) Go(func() error) {} 182 183 func _() { 184 var s []int 185 // errgroup.Group.Go() invokes Go routines 186 g := new(errgroup.Group) 187 for i, v := range s { 188 g.Go(func() error { 189 print(i) // want "loop variable i captured by func literal" 190 print(v) // want "loop variable v captured by func literal" 191 return nil 192 }) 193 } 194 195 for i, v := range s { 196 if i > 0 { 197 g.Go(func() error { 198 print(i) // want "loop variable i captured by func literal" 199 return nil 200 }) 201 } else { 202 g.Go(func() error { 203 print(v) // want "loop variable v captured by func literal" 204 return nil 205 }) 206 } 207 } 208 209 // Do not match other Group.Go cases 210 g1 := new(Group) 211 for i, v := range s { 212 g1.Go(func() error { 213 print(i) 214 print(v) 215 return nil 216 }) 217 } 218 } 219 220 // Real-world example from #16520, slightly simplified 221 func _() { 222 var nodes []interface{} 223 224 critical := new(errgroup.Group) 225 others := sync.WaitGroup{} 226 227 isCritical := func(node interface{}) bool { return false } 228 run := func(node interface{}) error { return nil } 229 230 for _, node := range nodes { 231 if isCritical(node) { 232 critical.Go(func() error { 233 return run(node) // want "loop variable node captured by func literal" 234 }) 235 } else { 236 others.Add(1) 237 go func() { 238 _ = run(node) // want "loop variable node captured by func literal" 239 others.Done() 240 }() 241 } 242 } 243 }