【问题标题】:Why does this anonymous func return the same instance of struct?为什么这个匿名函数返回相同的结构实例?
【发布时间】:2013-05-26 22:33:54
【问题描述】:
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)

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

【问题讨论】:

    标签: go


    【解决方案1】:

    您将两个接口与one == two 进行比较。让我们看看language specification对于这个表达式的含义是怎么说的:

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

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

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

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

    可能看起来像这样:

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

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

    【讨论】:

    • 是否可以将 &fake{} 结构体转换为 int 类型,它表示内存地址以进行比较?
    • 是的,使用不安全。但是如果你从两个相同的指针开始并将它们都转换为整数,你仍然会得到相同的比较。我会在回答中解释我的意思。
    • 对不起,如果我不清楚。我正在尝试实现 2 个随机结构的实例比较,而不是 2 个随机整数。我在上一条评论中的意思是,如何将结构类型“假”(或任何类型的结构)的内存地址转换为整数以进行内存位置比较,而不是使用整数进行比较。
    • 我了解您的代码在做什么(比较两个包含指向零大小结构的指针的接口),但我不明白您这样做是为了达到什么目的。如果你解释了你的意图,可能会有更好的方法来实现你想要做的事情。
    • 我想看看这两个对象是否属于同一个实例。例如,在 Java 中,您将比较对象的哈希码以确定两个对象是否是同一个实例。
    【解决方案2】:

    语言规范的最后一段:

    如果结构或数组类型不包含任何字段(或 元素,分别)具有大于零的大小。二 不同的零大小变量在内存中可能具有相同的地址。

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

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

    【讨论】:

      猜你喜欢
      • 2023-03-22
      • 2018-07-10
      • 2022-10-23
      • 2019-11-17
      • 2016-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多