处理具有相同键类型但不同值类型的映射

huangapple go评论86阅读模式
英文:

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

huangapple
  • 本文由 发表于 2014年9月11日 02:16:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/25772347.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定