Golang map with multiple keys per value

Better solution would be to use struct with two field as a key:

type key struct {
    url string
    id  int
}

m := make(map[key]MediaItem)
m[key{url: "http://...", id: 2}] = MediaItem{}

Staying with the map type, you can use 2 (3) different solutions:

With 2 maps

Easiest would be to build 2 maps, 1 where the keys are the urls, and 1 where the keys are the ids:

var byUrlMap map[string]*MediaItem
var byIdMap map[string]*MediaItem

Note that you should store pointers instead of structs for example to avoid duplicating the values.

If you need a MediaItem by id:

mi := byIdMap[id]

Similarly by url:

mi2 := byUrlMap[url]

With key prefixes

Another option can be to prefix the actual key values, but this is not so efficient, but as a result, you'll have only one map.

For example you could prefix URL keys with "url:" and ids with "id:" and store the same pointer value of course for both the url and id keys, for example:

var miMap = make(map[string]*MediaItem)

mi := &MediaItem{}
miMap["url:http://something"] = mi
miMap["id:1"] = mi

And getting an element:

mi2 := miMap["id:" + id]   // By id
mi3 := miMap["url:" + url] // By url

Using keys "as-is"

This is something similar to "With key prefixes": if you have guarantee that the URLs and ids will never be the same (meaning you will never have an id that is the same as another item's url and vice versa), you can simply use both keys without prefixes, and set the same value (pointer) to them.

The purpose of key prefixes was to make sure a final url key will never be the same as a final id key (achieved by using different prefixes for these 2 types of keys). But if this condition is naturally true (e.g. the string value of a numeric id will never be a valid url), we don't really need the prefixes:

var miMap = make(map[string]*MediaItem)

mi := &MediaItem{}
miMap["http://something"] = mi
miMap["1"] = mi

And getting an element:

mi2 := miMap[id]  // By id
mi3 := miMap[url] // By url

Tags:

Dictionary

Go