map [Task] int64其中Task是一个接口

Let's say I define the following interface in a Go library:

type Task interface {
    Do() error
}

func Register(task Task) { ... }

func GetId(task Task) int64 { ... }

In Register(), the library associates a unique int64 with each task instance. GetId() must return the identifier for the given task.

My initial idea was to store the association as a map[Task]int64. This seems to work fine, but I was told that it would break if an object implementing Task was not equality-comparable (for example, a struct containing a map). I still need to check if this is true.

I was going to try and use a slice of struct { task Task; id int64 } instead and just iterate over it, but that would still require equality comparable Task instances. And AFAIU there is no identity comparison in Go.

How can I have a robust mapping from Task instances to their ID?

EDIT: Both solutions proposed so far work, but they have the disadvantage that every Task implementation has to include some repetitive code to handle the IDs. I could provide that code in a TaskBase struct that could be embedded, but ideally I would prefer a solution that doesn't require implementations to even know about the IDs (they are internal to the library and have no meaning outside of it).

A more complete example: http://play.golang.org/p/1RzDiw7F9t

package main

import (
    "fmt"
    "math/rand"
)

type Task interface {
    Do() error
    ID() int64
}

type XTask struct {
    id int64
    // other stuff
}

func NewXTask( /*task parameters...*/) *XTask {
    t := &XTask{ /*initialize members*/}
    t.id = Register(t)
    // possibly more initialization...
    return t
}

func (t *XTask) Do() error  { return nil }  // stub
func (t *XTask) ID() int64  { return t.id }

var taskRegistry = map[int64]Task{}

func Register(t Task) int64 {
    var id int64
    for {
        id = rand.Int63()
        if _, exists := taskRegistry[id]; !exists {
            break
        }
    }
    taskRegistry[id] = t
    return id
}

func main() {
    t1 := NewXTask()
    t2 := NewXTask()
    fmt.Printf("%x
", t1.ID())
    fmt.Printf("%x
", t2.ID())
}

I used an ID method as Daniel suggested, and I turned the map backwards from the way you had it. This is because the Task objects know their own ID, so a map from Task to ID is not needed. A map from ID to task however, is useful for guaranteeing uniqueness. It might come in handy some other time if you find yourself with only an ID and you need the corresponding Task object.

Also note this example is not goroutine-safe. If you need that you will have to add synchronization.