2014-12-03 14 views
6

Come utilizzare la funzione come chiave della mappa? per esempio:Golang come utilizzare la funzione come chiave della mappa

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

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

coloro codice mostrerebbe un errore: invalid map key type Action

+0

Qual è il caso esatto uso? Un'interfaccia non sarebbe più semantica e più estensibile qui? –

+0

Ho bisogno di sapere se una funzione che ho ottenuto da un 'trie' è una funzione creata dalla funzione' X' o no .. – Kokizzu

risposta

2

Non puoi farlo direttamente, come già detto, ma è possibile sorta di è falso fare qualcosa di simile:

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

Questo è un po 'macchinoso, e onestamente penso che sia una pessima idea usare essenzialmente la versione stringa di un puntatore come chiave della mappa. Ma ... è almeno un'opzione se ne hai davvero bisogno.

+0

Funziona solo finché si mantengono le istanze del wrapper di funzione e le si riutilizza sempre . Creare 2 wrapper attorno alla stessa funzione non produce lo stesso risultato: http://play.golang.org/p/DdwzCTORBf – chakrit

+1

Non va bene ... aggiornerò la mia risposta. – Nerdmaster

11

Non è possibile utilizzare una funzione come chiave della mappa. Il language specification dice chiaramente:

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.

7

Non è possibile utilizzare funzioni come chiavi nelle mappe: il tipo di chiave deve essere paragonabile.

Da 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

quello che si potrebbe usare, a seconda del caso d'uso preciso, è un'interfaccia.

4

funzioni non possono essere tasti:

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

2

Mentre le funzioni non possono essere tasti, i puntatori di funzione possono.

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

+0

Funziona solo perché stai usando l'indirizzo di una variabile, che non è lo stesso di "puntatore di funzione". Ecco il tuo esempio con la stessa funzione assegnata a un'altra variabile, e la mappa risultante ha due voci, perché gli indirizzi variabili sono diversi: https://play.golang.org/p/8DBIR4h1jU –

Problemi correlati