github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/test/closure2.go (about)

     1  // run
     2  
     3  // Copyright 2015 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  // Check that these do not use "by value" capturing,
     8  // because changes are made to the value during the closure.
     9  
    10  package main
    11  
    12  func main() {
    13  	{
    14  		type X struct {
    15  			v int
    16  		}
    17  		var x X
    18  		func() {
    19  			x.v++
    20  		}()
    21  		if x.v != 1 {
    22  			panic("x.v != 1")
    23  		}
    24  
    25  		type Y struct {
    26  			X
    27  		}
    28  		var y Y
    29  		func() {
    30  			y.v = 1
    31  		}()
    32  		if y.v != 1 {
    33  			panic("y.v != 1")
    34  		}
    35  	}
    36  
    37  	{
    38  		type Z struct {
    39  			a [3]byte
    40  		}
    41  		var z Z
    42  		func() {
    43  			i := 0
    44  			for z.a[1] = 1; i < 10; i++ {
    45  			}
    46  		}()
    47  		if z.a[1] != 1 {
    48  			panic("z.a[1] != 1")
    49  		}
    50  	}
    51  
    52  	{
    53  		w := 0
    54  		tmp := 0
    55  		f := func() {
    56  			if w != 1 {
    57  				panic("w != 1")
    58  			}
    59  		}
    60  		func() {
    61  			tmp = w // force capture of w, but do not write to it yet
    62  			_ = tmp
    63  			func() {
    64  				func() {
    65  					w++ // write in a nested closure
    66  				}()
    67  			}()
    68  		}()
    69  		f()
    70  	}
    71  
    72  	{
    73  		var g func() int
    74  		for i := range [2]int{} {
    75  			if i == 0 {
    76  				g = func() int {
    77  					return i // test that we capture by ref here, i is mutated on every interation
    78  				}
    79  			}
    80  		}
    81  		if g() != 1 {
    82  			panic("g() != 1")
    83  		}
    84  	}
    85  
    86  	{
    87  		var g func() int
    88  		q := 0
    89  		for range [2]int{} {
    90  			q++
    91  			g = func() int {
    92  				return q // test that we capture by ref here
    93  					 // q++ must on a different decldepth than q declaration
    94  			}
    95  		}
    96  		if g() != 2 {
    97  			panic("g() != 2")
    98  		}
    99  	}
   100  
   101  	{
   102  		var g func() int
   103  		var a [2]int
   104  		q := 0
   105  		for a[func() int {
   106  			q++
   107  			return 0
   108  		}()] = range [2]int{} {
   109  			g = func() int {
   110  				return q // test that we capture by ref here
   111  					 // q++ must on a different decldepth than q declaration
   112  			}
   113  		}
   114  		if g() != 2 {
   115  			panic("g() != 2")
   116  		}
   117  	}
   118  }