Golang how to use function as map's key

谁都会走 提交于 2020-01-14 07:55:07

问题


How to use function as map's key? for example:

type Action func(int)
func test(a int) { }
func test2(a int) { }

func main() {
  x := map[Action]bool{}
  x[test] = true
  x[test2] = false
}

those code would show an error: invalid map key type Action


回答1:


You can use reflect.

    import (
       "reflect"
       "math"
    )


    func foo () {
       table := make(map[uintptr] string)
       table[reflect.ValueOf(math.Sin)] = "Sin"
       table[reflect.ValueOf(math.Cos)] = "Cos"
       println(table[reflect.ValueOf(math.Cos)])
    }



回答2:


You cannot use a function as a map key. The language specification clearly says:

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.




回答3:


You can't use functions as keys in maps : the key type must be comparable.

From Go blog :

map keys may be of any type that is comparable. The language spec defines this precisely, but in short, comparable types are boolean, numeric, string, pointer, channel, and interface types, and structs or arrays that contain only those types. Notably absent from the list are slices, maps, and functions; these types cannot be compared using ==, and may not be used as map key

What you might use, depending on your precise use case, is an interface.




回答4:


Functions cannot be keys:

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.

Source




回答5:


You cannot do this directly, as mentioned already, but you can sort of fake it you do something like this:

package main

import "fmt"

func a(i int) int {
    return i + 1
}

func b(i int) int {
    return i + 2
}

type Function func(int)int
type FunctionWrapper struct {
    f *Function
}

var fnMap = make(map[string]FunctionWrapper)

// MakeFunctionWrapper returns a unique FunctionWrapper per Function pointer, using fnMap to avoid having multiple values for the same function
func MakeFunctionWrapper(f Function) FunctionWrapper {
    key := fmt.Sprintf("%#v", f)
    data, ok := fnMap[key]
    if !ok {
        data = FunctionWrapper{&f}
        fnMap[key] = data
    }
    return data
}

func main() {
    functions := make(map[FunctionWrapper]bool)
    fa := MakeFunctionWrapper(a)
    fb := MakeFunctionWrapper(b)
    fb2 := MakeFunctionWrapper(b)
    functions[fa] = true
    functions[fb] = true
    functions[fb2] = false              // This overwrites the previous value since fb is essentially the same as fb2

    fmt.Println(functions[fa])          // "true"
    fmt.Println(functions[fb])          // "false"
    fmt.Println(functions[fb2])         // "false"
}

Check it out on the Go playground

This is a bit cumbersome, and I honestly think it's a very bad idea to essentially use the string version of a pointer as your map's key. But ... it's at least an option if you really need it.




回答6:


While functions can't be keys, function pointers can.

package main

import "fmt"

type strFunc *func() string

func main() {

    myFunc := func() string { return "bar" }
    m := make(map[strFunc]string)
    m[(strFunc)(&myFunc)] = "f"

    for f, name := range m {
        fmt.Println((*f)(), name)
    }
}

http://play.golang.org/p/9DdhYduX7E



来源:https://stackoverflow.com/questions/27267042/golang-how-to-use-function-as-maps-key

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!