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  }