我有一个名为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支持泛型,我该如何修复代码?
答案 0 :(得分:6)
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
答案 1 :(得分:2)
除了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
}
请注意,如果您使用此解决方案,则Keys
返回的密钥将包含接口本身包含的每个密钥值。因此,要获得实际值,您可能需要键入断言:
k := Keys(m2)
k1 := k[0].(int) // k[0] is an interface value, k1 is an int
答案 2 :(得分:1)
从 Go 1.18(2022 年初,除非出现延迟)开始,该语言最终将实现类型参数,您将能够轻松编写这样的函数:
package main
import (
"fmt"
"reflect"
)
func main() {
m2 := map[int]interface{}{
2: "string",
3: "int",
}
keys := Keys(m2)
fmt.Println(keys) // [2 3]
fmt.Println(reflect.TypeOf(keys)) // []int
}
func Keys[K comparable](m map[K]interface{}) (keys []K) {
for k := range m {
keys = append(keys, k)
}
return keys
}
注意,基于current proposal,类型参数K
上的类型约束是预先声明的标识符comparable
1,而不是{{1 }}。
这是因为映射键必须支持comparison operators:
<块引用>必须为键类型的操作数完整定义比较运算符 any
和 ==
因此您必须将 !=
限制为仅可比较的类型。
1:关于引入哪些预先声明的标识符仍在讨论中;类型参数实现完成后再回来查看