为什么这个匿名函数返回相同的结构体实例?

huangapple go评论107阅读模式
英文:

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

问题

为什么这个匿名函数返回相同的请求类型实例,我如何使其在每次调用时返回一个新的实例?

英文:
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?

答案1

得分: 6

你可以使用one == two来比较两个接口。让我们看看语言规范对这个表达式的含义有什么说法:

> 接口值是可比较的。如果两个接口值具有相同的动态类型和相等的动态值,或者两个接口值都为nil,则它们是相等的。
>
> 指针值是可比较的。如果两个指针值指向同一个变量,或者两个指针值都为nil,则它们是相等的。指向不同大小的零值变量的指针可能相等,也可能不相等。

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

鉴于此,你可以通过不使用指向零大小结构体的指针作为唯一值来解决你的问题。也许可以使用int类型代替?

代码可能如下所示:

type fake int

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

不清楚你想要实现什么,所以这可能或可能不是一个好的解决方案。

英文:

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.

答案2

得分: 1

语言规范的最后一段:

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

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

因此,正如接受的答案中所指出的那样,如果使用非空的结构体,您将看到您期望的结果。

英文:

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.

huangapple
  • 本文由 发表于 2013年5月25日 21:42:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/16750150.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定