英文:
Different pointers are equal?
问题
我正在尝试将一些二维平面上的点表示为整数对。我希望这些点是不可变的(按值传递),但每个点都有唯一的标识。为了实现这一点,我创建了一个包含两个整数和一个字符串指针的结构体。这个方法运行良好:
package main
import "fmt"
func main() {
s1 := ""
s2 := ""
p := Point{1,2,&s1}
p2 := Point{1,2,&s2}
fmt.Println(p2==p) // 希望输出 false
}
type Point struct{X int; Y int; id *string}
输出结果为 false
。
由于字符串实际上没有被用于任何操作(我只关心判断两个点是否相同),似乎使用指向 struct{}
的指针作为唯一引用的规范解决方案会更好:
package main
import "fmt"
func main() {
s1 := struct{}{}
s2 := struct{}{}
p := Point{1,2,&s1}
p2 := Point{1,2,&s2}
fmt.Println(p2==p) // 希望输出 false
}
type Point struct{X int; Y int; id *struct{}}
然而,现在两个指针是相等的:
输出结果为 true
。
为什么会这样?字符串也会发生这种情况吗?我应该使用 UUID 吗?
英文:
I'm trying to represent some points on a 2d plane as pairs of integers. I want the points to be immutable (pass-by-value), but also for each to have a unique identity. To accomplish this, I made a struct with two int
s and a *string
. This works fine:
package main
import "fmt"
func main() {
s1 := ""
s2 := ""
p := Point{1,2,&s1}
p2 := Point{1,2,&s2}
fmt.Println(p2==p) // want false
}
type Point struct{X int; Y int; id *string}
<!
$ go run a.go
false
Since the string
isn't actually used for anything (I only care about telling whether two points are the same), it seems like the canonical solution for making a unique reference like this would be to use a pointer to struct{}
instead:
package main
import "fmt"
func main() {
s1 := struct{}{}
s2 := struct{}{}
p := Point{1,2,&s1}
p2 := Point{1,2,&s2}
fmt.Println(p2==p) // want false
}
type Point struct{X int; Y int; id *struct{}}
However, now the two pointers are equal:
$ go run a.go
true
Why? Can this happen with strings as well? Should I use UUIDs instead?
答案1
得分: 7
空结构体struct{}{}
是特殊的。
参见:http://golang.org/ref/spec#Size_and_alignment_guarantees,其中写道:
如果结构体或数组类型不包含大小大于零的字段(或元素),则其大小为零。两个不同的零大小变量在内存中可能具有相同的地址。
你可以简单地在其中添加一个字段来确保唯一性。例如:
package main
import "fmt"
type token struct{ bool }
type Point struct {
X int
Y int
id *token
}
func main() {
p := Point{1, 2, &token{}}
p2 := Point{1, 2, &token{}}
fmt.Println(p2 == p) // 期望输出为 false
}
英文:
The empty struct struct{}{}
is special.
See: http://golang.org/ref/spec#Size_and_alignment_guarantees where it says:
> 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.
You can probably just put a field in there to get uniqueness. Something like:
package main
import "fmt"
type token struct{ bool }
type Point struct {
X int
Y int
id *token
}
func main() {
p := Point{1, 2, &token{}}
p2 := Point{1, 2, &token{}}
fmt.Println(p2 == p) // want false
}
答案2
得分: 2
为了区分两个不同的点,即使它们具有相同的坐标,可以使用地址。例如,
package main
import "fmt"
type Point struct {
X int
Y int
p *Point
}
func NewPoint(x, y int) Point {
p := Point{X: x, Y: y}
p.p = &p
return p
}
func main() {
x, y := 1, 2
p1 := NewPoint(x, y)
p2 := NewPoint(x, y)
fmt.Println(p1)
fmt.Println(p2)
fmt.Println(p1 == p1)
fmt.Println(p1 == p2)
}
输出:
{1 2 0x10328000}
{1 2 0x10328020}
true
false
英文:
To distinguish between two different points, even if they have the same coordinates, use addresses. For example,
package main
import "fmt"
type Point struct {
X int
Y int
p *Point
}
func NewPoint(x, y int) Point {
p := Point{X: x, Y: y}
p.p = &p
return p
}
func main() {
x, y := 1, 2
p1 := NewPoint(x, y)
p2 := NewPoint(x, y)
fmt.Println(p1)
fmt.Println(p2)
fmt.Println(p1 == p1)
fmt.Println(p1 == p2)
}
Output:
{1 2 0x10328000}
{1 2 0x10328020}
true
false
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论