英文:
Does Go allow specification of an interface for a map with particular key type?
问题
我写了一个函数,它可以从一个map[string]Foo返回一个排序后的字符串切片。我想知道创建一个通用的例程来从任何类型的map中返回一个排序后的字符串切片的最佳方法是什么。
有没有办法使用接口规范来实现这个?例如,有没有办法做到这样:
type MapWithStringKey interface {
<这里放一些代码>
}
要实现上面的接口,类型需要将字符串作为键。然后,我可以编写一个通用函数,返回满足类型要求的键的排序列表。
这是我目前使用reflect模块的最佳解决方案:
func SortedKeys(mapWithStringKey interface{}) []string {
keys := []string{}
typ := reflect.TypeOf(mapWithStringKey)
if typ.Kind() == reflect.Map && typ.Key().Kind() == reflect.String {
switch typ.Elem().Kind() {
case reflect.Int:
for key, _ := range mapWithStringKey.(map[string]int) {
keys = append(keys, key)
}
case reflect.String:
for key, _ := range mapWithStringKey.(map[string]string) {
keys = append(keys, key)
}
// ... 根据需要添加更多的情况
default:
log.Fatalf("错误:SortedKeys()不处理%s\n", typ)
}
sort.Strings(keys)
} else {
log.Fatalln("错误:SortedKeys()的参数不是map[string]...")
}
return keys
}
尽管在编译时我们应该知道mapWithStringKey参数的确切类型,但我被迫为每个支持的类型编写类型断言。
英文:
I wrote a function that would return a sorted slice of strings from a map[string]Foo. I'm curious what is the best way to create a generic routine that can return a sorted slice of strings from any type that is a map with strings as keys.
Is there a way to do it using an interface specification? For example, is there any way to do something like:
type MapWithStringKey interface {
<some code here>
}
To implement the interface above, a type would need strings as keys. I could then write a generic function that returns a sorted list of keys for fulfilling types.
This is my current best solution using the reflect module:
func SortedKeys(mapWithStringKey interface{}) []string {
keys := []string{}
typ := reflect.TypeOf(mapWithStringKey)
if typ.Kind() == reflect.Map && typ.Key().Kind() == reflect.String {
switch typ.Elem().Kind() {
case reflect.Int:
for key, _ := range mapWithStringKey.(map[string]int) {
keys = append(keys, key)
}
case reflect.String:
for key, _ := range mapWithStringKey.(map[string]string) {
keys = append(keys, key)
}
// ... add more cases as needed
default:
log.Fatalf("Error: SortedKeys() does not handle %s\n", typ)
}
sort.Strings(keys)
} else {
log.Fatalln("Error: parameter to SortedKeys() not map[string]...")
}
return keys
}
Click for Go Playground version
I'm forced to code type assertions for each supported type even though at compile time, we should know the exact type of the mapWithStringKey parameter.
答案1
得分: 5
你不能创建部分类型。但是你可以定义一个满足你需求的接口:
type SortableKeysValue interface {
// 返回需要排序的字符串
Keys() []string
}
func SortedKeys(s SortableKeysValue) []string {
keys := s.Keys()
sort.Strings(keys)
return keys
}
type MyMap map[string]string
func (s MyMap) Keys() []string {
keys := make([]string, 0, len(s))
for k, _ := range s {
keys = append(keys, k)
}
return keys
}
在这里尝试一下:http://play.golang.org/p/vKfri-h4Cp
英文:
You cannot make partial types. But you can define an interface which serves your purpose:
type SortableKeysValue interface {
// a function that returns the strings to be sorted
Keys() []string
}
func SortedKeys(s SortableKeysValue) []string {
keys := s.Keys()
sort.Strings(keys)
return keys
}
type MyMap map[string]string
func (s MyMap) Keys() []string {
keys := make([]string, 0, len(s))
for k, _ := range s {
keys = append(keys, k)
}
return keys
}
Try it here: http://play.golang.org/p/vKfri-h4Cp
答案2
得分: 0
希望能帮到你(go-1.1):
package main
import (
"fmt"
"reflect"
)
var m = map[string]int{"a": 3, "b": 4}
func MapKeys(m interface{}) (keys []string) {
v := reflect.ValueOf(m)
for _, k := range v.MapKeys() {
keys = append(keys, k.Interface().(string))
}
return
}
func main() {
fmt.Printf("%#v\n", MapKeys(m))
}
英文:
Hope that helps (go-1.1):
package main
import (
"fmt"
"reflect"
)
var m = map[string]int{"a": 3, "b": 4}
func MapKeys(m interface{}) (keys []string) {
v := reflect.ValueOf(m)
for _, k := range v.MapKeys() {
keys = append(keys, k.Interface().(string))
}
return
}
func main() {
fmt.Printf("%#v\n", MapKeys(m))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论