Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this anonymous func return the same instance of struct?

Tags:

go

package main

import "fmt"

type fake struct {
}

func main() {
    f := func() interface{} {
        return &fake{}
    }

    one := f()
    two := f()

    fmt.Println("Are equal?: ", one == two)
    fmt.Printf("%p", one)
    fmt.Println()
    fmt.Printf("%p", two)
    fmt.Println()
}

(http://play.golang.org/p/wxCUUCyz98)

Why does this anonymous func return the same instance of the requested type and how can i make it return a new one on each call?

like image 239
Dante Avatar asked Mar 24 '23 20:03

Dante


2 Answers

You compare two interfaces with one == two. Let's see what the language specification has to say on the meaning of this expression:

Interface values are comparable. Two interface values are equal if they have identical dynamic types and equal dynamic values or if both have value nil.

Pointer values are comparable. Two pointer values are equal if they point to the same variable or if both have value nil. Pointers to distinct zero-size variables may or may not be equal.

In your example, both one and two are both interface values, and they have the same dynamic type (*fake). Their dynamic values are both pointers to a zero-sized object though, and as you can read above, equality may or may not hold in this case.

Given this, you can solve your problem by not using pointers to zero-sized structs as unique values. Perhaps use an int instead?

That might look like this:

type fake int

func main() {
    var uniq fake
    f := func() interface{} {
        uniq++
        return uniq
    }
    ...
}

It's not clear what you're trying to achieve, so this may or may not be a good solution for you.

like image 87
Paul Hankin Avatar answered Apr 24 '23 17:04

Paul Hankin


The final paragraph of the language spec:

A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory.

http://golang.org/ref/spec#Size_and_alignment_guarantees

So as noted in the accepted answer, you will see what you expect if you use a non-empty struct.

like image 36
Dijkstra Avatar answered Apr 24 '23 18:04

Dijkstra