我试图将2d平面上的某些点表示为整数对。我希望这些点是不可变的(按值传递),但每个点都有一个唯一的标识。为了实现这一点,我创建了一个包含两个int
和一个*string
的结构。这很好用:
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
由于string
实际上并没有用于任何事情(我只关心两点是否相同),看起来像这样制作一个独特参考的规范解决方案就是使用指向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) // want false
}
type Point struct{X int; Y int; id *struct{}}
但是,现在两个指针是相同的:
$ go run a.go
true
为什么呢?这也可以用字符串发生吗?我应该使用UUID吗?
答案 0 :(得分: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) // want false
}
答案 1 :(得分: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