英文:
Handle maps with same key type but different value type
问题
我遇到了这个问题几次,当我想以类似的方式使用地图的键,但地图中的值是不同的。我以为我可以编写一个函数,以我想要的键类型和interface{}作为值类型,但它不起作用。
func main() {
mapOne := map[string]int
mapTwo := map[string]double
mapThree := map[string]SomeStruct
useKeys(mapOne)
}
func useKeys(m map[string]interface{}) {
//在这里处理键
}
不确定是否有一种优雅的方法来做到这一点,我只是觉得为不同的值重写简单的东西有点浪费。
英文:
I have run into this problem a few times when wanting to use keys of maps in a similar way but the values in the maps are different. I thought I could write a function that takes the key type I want with interface{} as the value type but it doesn't work.
func main() {
mapOne := map[string]int
mapTwo := map[string]double
mapThree := map[string]SomeStruct
useKeys(mapOne)
}
func useKeys(m map[string]interface{}) {
//something with keys here
}
Not sure if there is an elegant way to do this I just feel waist full rewriting simple things for different values.
答案1
得分: 18
尽管Go语言中的映射和切片本身是泛型的,但它们不是协变的(也不能是,因为接口不是泛型)。这是使用没有泛型的语言时的一部分工作,你将不得不重复一些东西。
如果你只是需要获取任意映射的键,你可以使用反射来实现:
func useKeys(m interface{}) {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Map {
fmt.Println("not a map!")
return
}
keys := v.MapKeys()
fmt.Println(keys)
}
英文:
Though maps and slices in go are generic themselves, they are not covariant (nor could they be, since interfaces aren't generics). It's part of working with a language that doesn't have generics, you will have to repeat some things.
If you really just need to get the keys of any old map, you can use reflection to do so:
func useKeys(m interface{}) {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Map {
fmt.Println("not a map!")
return
}
keys := v.MapKeys()
fmt.Println(keys)
}
答案2
得分: 12
Go 1.18
你可以使用类型参数(泛型)编写这样的函数:
func useKeys[V any](m map[string]V) V {
return m["foo"]
}
然后可以这样使用它:
func main() {
m1 := map[string]int{"foo": 1}
m2 := map[string]float64{"foo": 4.5}
m3 := map[string]*SomeStruct{}
fmt.Println(useKeys(m1))
fmt.Println(useKeys(m2))
fmt.Println(useKeys(m3))
}
如你所见,类型参数 V
与映射值进行统一,这样你就可以明确要求 useKeys
的调用者只能传递键为 string
的映射。
你可以在 GoTip Playground 上查看示例:https://gotipplay.golang.org/p/epFA2_9u5l5
英文:
Go 1.18
You can write a function with type parameters (generic) for this:
func useKeys[V any](m map[string]V) V {
return m["foo"]
}
And use it as:
func main() {
m1 := map[string]int{"foo": 1}
m2 := map[string]float64{"foo": 4.5}
m3 := map[string]*SomeStruct{}
fmt.Println(useKeys(m1))
fmt.Println(useKeys(m2))
fmt.Println(useKeys(m3))
}
As you can see, the type parameter V
unifies with the map value, so that you can explicitly force callers of useKeys
to pass maps whose keys are string
only.
You can see this on the GoTip Playground: https://gotipplay.golang.org/p/epFA2_9u5l5
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论