如何获取地图的键

Goi*_*Way 3 generics go go-reflect

我有一个命名函数Keys()来获取地图的所有键,这里是代码:

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
}
Run Code Online (Sandbox Code Playgroud)

但是我得到了

cannot use m2 (type map[int]interface {}) as type map[interface {}]interface {} in argument to Keys
Run Code Online (Sandbox Code Playgroud)

Go支持泛型,我该如何修复代码?

小智 6

1- Golang是强类型语言,因此map[int]interface{}与之不兼容map[interface{}]interface{}.
int是不同的类型interface{},并看到:Go:接口{}的含义是什么?

2-不,Golang不支持泛型,这非常好,因为它使语言简单快速.


你有一些选择:

如果您不想更改所使用的地图类型:
1-您可以将该功能编辑为:func Keys(m map[int]interface{}) []int,就像这个工作示例代码:

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
}
Run Code Online (Sandbox Code Playgroud)

输出(可能不是按顺序):

[2 3]
Run Code Online (Sandbox Code Playgroud)

2-或者你可以编辑函数:func Keys(m map[int]interface{}) []interface{},像这个工作示例代码:

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
}
Run Code Online (Sandbox Code Playgroud)

输出(可能不是按顺序):

[2 3]
Run Code Online (Sandbox Code Playgroud)

如果您不想更改使用的Keys功能:
3-您可以将地图编辑为:map[interface{}]interface{},如下工作示例代码:

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
}
Run Code Online (Sandbox Code Playgroud)

4-此外,您可以reflect在某些用例中使用包,但性能(速度)会受到影响.
并参见:反思的法则


abh*_*ink 6

除了 Amd 的解决方案,如果您不想更改使用的地图类型,您还可以使用反射库。

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

    k := Keys(m2)

    fmt.Printf("Keys: %v\n", 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

}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您使用此解决方案,则返回的键Keys将包含包装在接口本身中的每个键值。因此,要获得实际值,您可能必须进行类型断言:

k := Keys(m2)
k1 := k[0].(int) // k[0] is an interface value, k1 is an int
Run Code Online (Sandbox Code Playgroud)

工作代码