We've just have a discussion with a colleague about the case of what
exactly variable would a function literal close over, if it calls a
method on a field of a struct-typed variable available in the scope of
the enclosing function.

Here's the code:

-------------------------------8<--------------------------------
    package main
    
    import (
        "fmt"
    )
    
    type Foo struct {
        val int
    }
    
    func (foo *Foo) Show() {
        fmt.Println(foo.val)
    }
    
    type Bar struct {
        foo *Foo
    }
    
    func main() {
        foo := &Foo{123}
        bar := &Bar{foo}
        
        fn := func() {
                bar.foo.Show()
        }
        
        fn()
        
        bar.foo = &Foo{456}
        
        fn()
    }
-------------------------------8<--------------------------------

(Playground link: [1]).

and the dispute was about whan variable would fn() close over.

I proposed that it will close over bar.foo since it's the "narrowest"
variable needed to be able to call Show().
As it turned out, I was wrong, and fn() closes over bar.

My line of reasoning stems from the following passage from the spec [2]:

| Structured variables of array, slice, and struct types have elements and
| fields that may be addressed individually. Each such element acts like a
| variable.

which seem to suggest in the case above bar.foo is a variable, and since
bar itself is not needed to call the Show() method provided by the
bar.foo's type, the function literal would close over the field alone
(presumably internally storing a pointer to it).

The part of the spec which discusses function literals [3] states:

| Function literals are closures: they may refer to variables defined in a
| surrounding function. Those variables are then shared between the
| surrounding function and the function literal, and they survive as long
| as they are accessible.

So there is no clearly defined rule of how the compiler decides what to
capture.


I've got hunch that may be [2] really has concurrent access in mind when
it states "Each such element acts like a variable", and this does not
apply to other cases.


Can anyone please explain where there is a flaw in my line of reasoning
which led me to a wrong conclusion?

 1. https://play.golang.org/p/_VfdzQDNZR
 2. https://golang.org/ref/spec#Variables
 3. https://golang.org/ref/spec#Function_literals

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to