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