如何获取地图的key
How to get keys of map
我有一个名为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
}
但是我得到了
cannot use m2 (type map[int]interface {}) as type map[interface {}]interface {} in argument to Keys
Go 是否支持泛型?我应该如何修复我的代码?
1- Golang 是强类型语言,所以 map[int]interface{}
与 map[interface{}]interface{}
不兼容。
int
与 interface{}
的类型不同,
并查看:Go: What's the meaning of interface{}?
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
}
输出(可能顺序不对):
[2 3]
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
}
输出(可能顺序不对):
[2 3]
如果您不想更改使用的 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
}
4-您也可以在某些用例中使用 reflect
包,但会降低性能(速度)。
请参阅:The Laws of Reflection
除了 Amd 的解决方案,如果您不想更改使用的地图类型,您还可以使用 reflect 库。
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
}
请注意,如果您使用此解决方案,Keys
返回的键将包含包装在接口本身中的每个键值。因此,要获得实际值,您可能必须执行类型断言:
k := Keys(m2)
k1 := k[0].(int) // k[0] is an interface value, k1 is an int
从 Go 1.18(测试版发布)开始,该语言添加了类型参数,您可以轻松编写如下函数:
func Keys[K comparable, V any](m map[K]V) []K {
keys := make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
用法示例:
func main() {
m := map[int]string{2: "string", 3: "int"}
keys := Keys(m)
fmt.Println(keys) // [2 3]
fmt.Println(reflect.TypeOf(keys)) // []int
m2 := map[string]int{"a": 1, "b": 2}
keys2 := Keys(m2)
fmt.Println(keys2) // [a b]
fmt.Println(reflect.TypeOf(keys2)) // []string
}
游乐场:https://gotipplay.golang.org/p/pdsI2H7w-N4
注意,基于current proposal,类型参数K
的类型约束是预先声明的标识符comparable
,而不是any
。
这是因为地图键必须支持comparison operators。因此,您必须将 K
限制为仅可比较的类型。
或者基于this accepted proposal the new package maps
is also available to accomplish the same thing. However this is not yet in the standard library. Instead it was included in golang.org/x/exp
,因此不在 Go 1 兼容性承诺范围内。
maps.Keys
和上面的函数的区别在于maps.Keys
是在M
上参数化的(除了K
和V
),与近似约束 ~map[K]V
。这允许所有具有底层 map
:
的已定义类型
type MyMap map[string]int
用法基本相同:
package main
import (
"fmt"
"reflect"
"golang.org/x/exp/maps"
)
func main() {
m := map[int]string{2: "string", 3: "int"}
keys := maps.Keys(m)
fmt.Println(keys) // [2 3]
fmt.Println(reflect.TypeOf(keys)) // []int
}
我有一个名为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
}
但是我得到了
cannot use m2 (type map[int]interface {}) as type map[interface {}]interface {} in argument to Keys
Go 是否支持泛型?我应该如何修复我的代码?
1- Golang 是强类型语言,所以 map[int]interface{}
与 map[interface{}]interface{}
不兼容。
int
与 interface{}
的类型不同,
并查看:Go: What's the meaning of interface{}?
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
}
输出(可能顺序不对):
[2 3]
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
}
输出(可能顺序不对):
[2 3]
如果您不想更改使用的 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
}
4-您也可以在某些用例中使用 reflect
包,但会降低性能(速度)。
请参阅:The Laws of Reflection
除了 Amd 的解决方案,如果您不想更改使用的地图类型,您还可以使用 reflect 库。
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
}
请注意,如果您使用此解决方案,Keys
返回的键将包含包装在接口本身中的每个键值。因此,要获得实际值,您可能必须执行类型断言:
k := Keys(m2)
k1 := k[0].(int) // k[0] is an interface value, k1 is an int
从 Go 1.18(测试版发布)开始,该语言添加了类型参数,您可以轻松编写如下函数:
func Keys[K comparable, V any](m map[K]V) []K {
keys := make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
用法示例:
func main() {
m := map[int]string{2: "string", 3: "int"}
keys := Keys(m)
fmt.Println(keys) // [2 3]
fmt.Println(reflect.TypeOf(keys)) // []int
m2 := map[string]int{"a": 1, "b": 2}
keys2 := Keys(m2)
fmt.Println(keys2) // [a b]
fmt.Println(reflect.TypeOf(keys2)) // []string
}
游乐场:https://gotipplay.golang.org/p/pdsI2H7w-N4
注意,基于current proposal,类型参数K
的类型约束是预先声明的标识符comparable
,而不是any
。
这是因为地图键必须支持comparison operators。因此,您必须将 K
限制为仅可比较的类型。
或者基于this accepted proposal the new package maps
is also available to accomplish the same thing. However this is not yet in the standard library. Instead it was included in golang.org/x/exp
,因此不在 Go 1 兼容性承诺范围内。
maps.Keys
和上面的函数的区别在于maps.Keys
是在M
上参数化的(除了K
和V
),与近似约束 ~map[K]V
。这允许所有具有底层 map
:
type MyMap map[string]int
用法基本相同:
package main
import (
"fmt"
"reflect"
"golang.org/x/exp/maps"
)
func main() {
m := map[int]string{2: "string", 3: "int"}
keys := maps.Keys(m)
fmt.Println(keys) // [2 3]
fmt.Println(reflect.TypeOf(keys)) // []int
}