Peter Brennan
Peter Brennan

Reputation: 1376

map with function pointer as key in go

I recently used a map in one of my golang projects, that had function pointers as keys like this:

map[*functiontype] somestructtype

One of my colleagues said this was a bad idea, so now I am unsure of this being feasible. I initially deemed it ok, because method pointers can be checked for equality and are immutable. Can someone provide some reasoning on that matter?

Complete example:

package main

import "fmt"

type s struct {
    string
}

type f func() string
func func1() string { return "func 1" }
func func2() string { return "func 2" }

func main() {
    // make two functions and two pointers to them
    f1, f2 := func1, func2
    p1, p2 := (*f)(&f1), (*f)(&f2)

    // make a map of their function pointers
    m := make(map[*f]s)
    m[p1] = s{"struct 1"}
    m[p2] = s{"struct 2"}

    // print out the mapping
    printmapping(m, p1, p2)

    // reverse the pointers and have that printed
    p1, p2 = (*f)(&f2), (*f)(&f1)
    printmapping(m, p1, p2)
}

func printmapping(m map[*f]s, p1, p2 *f) {
    fmt.Println("pointer 1:", m[(*f)(p1)])
    fmt.Println("pointer 2:", m[(*f)(p2)])
}

Upvotes: 10

Views: 4587

Answers (2)

user1804599
user1804599

Reputation:

If the key type is a pointer to a function type (such as *func()) then it's totally fine and the semantics are as expected: equal pointers are equal keys.

However, looking up the values in the map may not work out as you may expect: example. Here &f takes the address of the local variable, which is never the same for different invocations of Add and Find. The following of course could be useful: http://play.golang.org/p/F9jyUxzJhz


If it is not a pointer, it's a bad idea because it's impossible from Go 1 onwards. According to the language specification (live demo):

The comparison operators == and != must be fully defined for operands of the key type; thus the key type must not be a function, map, or slice.

== and != aren't defined for functions since the problem of comparing functions for equality is undecidable.

Upvotes: 7

peterSO
peterSO

Reputation: 166578

Your question is too abstract to be meaningful. Give us code for a real example. How to create a Minimal, Complete, and Verifiable example..

For example, do you mean something like this?

package main

import "fmt"

type f func(int) int

type s struct{ i int }

func f1(i int) int { return i }

func f2(i int) int { return i * i }

func main() {
    p1, p2 := f1, f2
    fmt.Println(p1, &p1, p2, &p2)
    m := make(map[*f]s)
    m[(*f)(&p1)] = s{f1(42)}
    m[(*f)(&p2)] = s{f2(42)}
    fmt.Println(m)
    p1, p2 = f2, f1
    fmt.Println(m)
    fmt.Println(p1, &p1, p2, &p2)
}

Output:

0x20000 0x1040a120 0x20020 0x1040a128
map[0x1040a120:{42} 0x1040a128:{1764}]
map[0x1040a128:{1764} 0x1040a120:{42}]
0x20020 0x1040a120 0x20000 0x1040a128

Upvotes: 4

Related Questions