Golang как использовать функцию в качестве ключа карты
Как использовать функцию в качестве ключа карты? например:
type Action func(int)
func test(a int) { }
func test2(a int) { }
func main() {
x := map[Action]bool{}
x[test] = true
x[test2] = false
}
этот код покажет ошибку:invalid map key type Action
6 ответов
можно использовать 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)])
}
вы не можете использовать функцию в качестве ключа карты. The спецификация языка четко говорит:
операторы сравнения == и != должно быть полностью определено для операндов типа ключа; таким образом, тип ключа не должен быть функцией, картой или срезом.
вы не можете использовать функции в качестве ключей в картах : тип ключа должен быть сопоставимым.
с перейти в блог :
ключи карты могут быть любого сопоставимого типа. Спецификация языка определяет это точно, но, короче говоря, сопоставимые типы являются булевыми, числовые, строковые, указательные, канальные и интерфейсные типы, а также структуры или массивы, содержащие только эти типы. заметно отсутствуют в списке ломтики, карты и функции; эти типы нельзя сравнивать с помощью ==, и не может использоваться в качестве ключа карты
то, что вы можете использовать, в зависимости от вашего конкретного случая использования, является интерфейсом.
функции не могут быть кнопки:
операторы сравнения == и != должно быть полностью определено для операндов типа ключа; таким образом, тип ключа не должен быть функцией, картой или срезом.
вы не можете сделать это напрямую, как уже говорилось, но вы можете вроде фейк это вы делаете что-то вроде этого:
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"
}
проверьте это на Go playground
Это немного громоздко, и я честно думаю, что очень плохая идея по существу использовать строковую версию указателя в качестве ключа вашей карты. Но... это, по крайней мере, вариант, если он вам действительно нужен.
в то время как функции не могут быть ключами, указатели функций могут.
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)
}
}