Go是否允许为具有特定键类型的地图指定接口?

Does Go allow specification of an interface for a map with particular key type?

我编写了一个函数,该函数将从map[string]foo返回已排序的字符串片段。我很好奇,创建一个通用例程的最佳方法是什么,它可以从任何类型的映射中返回字符串的已排序部分,其中字符串作为键。

有没有一种方法可以使用接口规范来做到这一点?例如,是否有任何方法可以做到:

1
2
3
type MapWithStringKey interface {
    <some code here>
}

要实现上面的接口,类型需要字符串作为键。然后我可以编写一个通用函数,该函数返回满足类型的键的排序列表。

这是我目前使用反射模块的最佳解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
", typ)
        }
        sort.Strings(keys)
    } else {
        log.Fatalln("Error: parameter to SortedKeys() not map[string]...")
    }
    return keys
}

点击进入游乐场版本

我不得不为每个支持的类型编写类型断言代码,即使在编译时,我们应该知道mapwithStringKey参数的确切类型。


不能生成分部类型。但是您可以定义一个满足您的目的的接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
}

在这里试试:http://play.golang.org/p/vkfri-h4cp


希望有帮助(go-1.1):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
", MapKeys(m))
}