5

please review code

package main
import (
    "fmt"
    "reflect"
)
func main() {

    factory := func  (name string) func(){
        return func (){
            fmt.Println(name)
        }
    }
    f1 := factory("f1")
    f2 := factory("f2")

    pf1 := reflect.ValueOf(f1)
    pf2 := reflect.ValueOf(f2)

    fmt.Println(pf1.Pointer(), pf2.Pointer())
    fmt.Println(pf1.Pointer() == pf2.Pointer())

    f1()
    f2()
}

the result:

4199328 4199328
true
f1
f2

Why get to the same address of the closure function! Or to how to get a unique address!

dr.xsty
  • 53
  • 1
  • 4

3 Answers3

9

Function pointers denote the code of the function. And the code of an anonymous function created by function literal is only stored once in memory, no matter how many times the code that returns the anonymous function value runs. This means all function values (or more precisely the function pointers) will be the same.

So you can't distinguish between the values stored in f1 and f2: they denote the same code block to be executed when they are called.

The function value that is returned by the function value stored in your factory variable is a closure. The environment (local variables and function parameters) referred by it survives for as long as it is accessible. In your case this means since the function values in f1 and f2 refer to the name argument of the enclosing anonymous function, they ("they" as from multiple calls) will be retained as long as the function values (in f1 and f2) are accessible. This is the only thing that makes them "different" or unique, but this is invisible from the "outside".

Would you go ahead and print the address of name in the closure, you'd see they are different variables for multiple values of the closure, but it is the same if the same closure (function value) is called again. First modify the closure to also print the address of name:

factory := func(name string) func() {
    return func() {
        fmt.Println(name, &name)
    }
}

And call f1 and f2 multiple times:

f1()
f2()
f1()
f2()

Output:

f1 0x1040a120
f2 0x1040a130
f1 0x1040a120
f2 0x1040a130

As you can see, the name argument is retained and the same name argument is used again if the same closure is invoked again.

icza
  • 389,944
  • 63
  • 907
  • 827
  • This question and answer were very interesting. I found http://stackoverflow.com/q/9643205/1103700 was a similar question (not about closures though) and the answers enlightening. The Go designers didn't seem to want function or closure comparisons - even with reflect. So there are some work arounds the folks have come up with - just as the Go designers would have hoped I expect. – WeakPointer Mar 21 '16 at 14:56
5

https://golang.org/pkg/reflect/#Value.Pointer

If v's Kind is Func, the returned pointer is an underlying code pointer, but not necessarily enough to identify a single function uniquely. The only guarantee is that the result is zero if and only if v is a nil func Value.

user1431317
  • 2,674
  • 1
  • 21
  • 18
1

Actually, *func() type in Go is equivalent to void (*)(void) type in C. (I know this because I use cgo often.)

And a Go func() is defined as a literal, meaning that it's something like a blob of bytes that represent machine code, rather than a function pointer.

Note that everything is passed by value in Go, and even a function is not an exception.

var f1 func() = ...
reflect.ValueOf(f1)

When you do that, I think you're trying to get the first 8 bytes of a code block called f1, and that is not an address to that function.

In current version of Go you can't take an address of a func() because an anonymous func() is only a literal denoting a code block that's located nowhere in memory. So you can't get an address to that.

Coconut
  • 2,024
  • 18
  • 25