4
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 )

为什么这个匿名函数返回请求类型的相同实例,我怎样才能让它在每次调用时返回一个新实例?

4

2 回答 2

6

您将两个接口与one == two. 让我们看看语言规范对这个表达式的含义是怎么说的:

接口值具有可比性。如果两个接口值具有相同的动态类型和相同的动态值,或者两者都具有值 nil,则它们是相等的。

指针值是可比较的。如果两个指针值指向同一个变量,或者两者的值都为零,则它们的值相等。指向不同的零大小变量的指针可能相等,也可能不相等。

在您的示例中,两者onetwo都是接口值,并且它们具有相同的动态类型(*fake)。不过,它们的动态值都是指向零大小对象的指针,正如您在上面所读到的,在这种情况下,等式可能成立,也可能不成立。

鉴于此,您可以通过不使用指向零大小结构的指针作为唯一值来解决您的问题。也许改用一个int

这可能看起来像这样:

type fake int

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

目前尚不清楚您要达到的目标,因此这对您来说可能是也可能不是一个好的解决方案。

于 2013-05-25T13:53:25.007 回答
1

语言规范的最后一段:

如果结构或数组类型不包含大小大于零的字段(或元素),则其大小为零。两个不同的零大小变量在内存中可能具有相同的地址。

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

因此,如已接受的答案中所述,如果您使用非空结构,您将看到您所期望的。

于 2013-05-26T14:33:54.713 回答