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