如何获取地图钥匙

I have a function named Keys() to get all the keys of a map, here is the code:

func main() {
    m2 := map[int]interface{}{
        2:"string",
        3:"int",
    }
    fmt.Println(Keys(m2))
}
func Keys(m map[interface{}]interface{}) (keys []interface{}) {
    for k := range m {
        keys = append(keys, k)
    }
    return keys
}

But I got

cannot use m2 (type map[int]interface {}) as type map[interface {}]interface {} in argument to Keys

Does Go support generics and how should I fix my code?

1- Golang is strongly typed language, So the map[int]interface{} is not compatible with map[interface{}]interface{}.
int is different type than interface{}, and see: Go: What's the meaning of interface{}?

2- No, Golang doesn't support generics, and this is very good, because it makes language simple and fast.


You have some options:

If you don't want to change the type of map used:
1- You may edit the function to: func Keys(m map[int]interface{}) []int, like this working sample code:

package main

import "fmt"

func main() {
    m2 := map[int]interface{}{
        2: "string",
        3: "int",
    }
    fmt.Println(Keys(m2))
}

func Keys(m map[int]interface{}) []int {
    keys := make([]int, len(m))
    i := 0
    for k := range m {
        keys[i] = k
        i++
    }
    return keys
}

output ( may not be in order):

[2 3]

2- Or you may edit the function to: func Keys(m map[int]interface{}) []interface{}, like this working sample code:

package main

import "fmt"

func main() {
    m2 := map[int]interface{}{
        2: "string",
        3: "int",
    }
    fmt.Println(Keys(m2))
}

func Keys(m map[int]interface{}) []interface{} {
    keys := make([]interface{}, len(m))
    i := 0
    for k := range m {
        keys[i] = k
        i++
    }
    return keys
}

output ( may not be in order):

[2 3]

If you don't want to change the Keys function used:
3- You may edit the map to: map[interface{}]interface{}, like this working sample code:

package main

import "fmt"

func main() {
    m2 := map[interface{}]interface{}{
        2: "string",
        3: "int",
    }
    fmt.Println(Keys(m2))
}

func Keys(m map[interface{}]interface{}) []interface{} {
    keys := make([]interface{}, len(m))
    i := 0
    for k := range m {
        keys[i] = k
        i++
    }
    return keys
}

4- Also you may use reflect package for some use cases, but with the performance (speed) penalty.
And See: The Laws of Reflection

Besides Amd's solution, you can also make use of the reflect library if you do not want to change the type of map used.

func main() {
    m2 := map[int]interface{}{
        2: "string",
        3: "int",
    }

    k := Keys(m2)

    fmt.Printf("Keys: %v
", k)
}

func Keys(m interface{}) (keys []interface{}) {
    v := reflect.ValueOf(m)
    if v.Kind() != reflect.Map {
        fmt.Errorf("input type not a map: %v", v)
    }

    for _, k := range v.MapKeys() {
        keys = append(keys, k.Interface())
    }
    return keys

}

Note that if you use this solution, the returned keys from Keys will contain each key value wrapped in an interface itself. So to get the actual value you might have to do type assertions:

k := Keys(m2)
k1 := k[0].(int) // k[0] is an interface value, k1 is an int

Working Code.