2

map[string]Fooから文字列のソートされたスライスを返す関数を作成しました。文字列をキーとして持つマップである任意のタイプから文字列のソートされたスライスを返すことができるジェネリックルーチンを作成するための最良の方法は何であるか興味があります。

インターフェイス仕様を使用してそれを行う方法はありますか?たとえば、次のようなことを行う方法はありますか?

type MapWithStringKey interface {
    <some code here>
}

上記のインターフェイスを実装するには、型にキーとして文字列が必要です。次に、型を満たすためのキーのソートされたリストを返すジェネリック関数を書くことができます。

これは、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)
            }
            // ... 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
}

GoPlaygroundバージョンはクリックしてください

コンパイル時にmapWithStringKeyパラメーターの正確な型を知っている必要がありますが、サポートされている型ごとに型アサーションをコーディングする必要があります。

4

2 に答える 2

5

部分型を作成することはできません。ただし、目的に合わせてインターフェイスを定義できます。

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

于 2012-11-08T16:07:10.883 に答える
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))
}
于 2013-07-30T12:50:17.397 に答える