不同的指针是否相等?

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 ints 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?

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
}

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