Search code examples
gogeneric-programming

How to get a slice of keys from map in golang uniformly?


I tried

func Keys(m map[string]interface{}) []string {
    keys := make([]string, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }
    return keys
}

but

cannot use m (type map[string]int) as type map[string]interface {} in argument to Keys

I know that golang doesn't support generics, so is it possible to get keys slice uniformly?


Solution

  • Use the reflect package to get the string keys from a map with arbitrary value type:

    func Keys(v interface{}) ([]string, error) {
      rv := reflect.ValueOf(v)
      if rv.Kind() != reflect.Map {
        return nil, errors.New("not a map")
      }
      t := rv.Type()
      if t.Key().Kind() != reflect.String {
        return nil, errors.New("not string key")
      }
      var result []string
      for _, kv := range rv.MapKeys() {
        result = append(result, kv.String())
      }
      return result, nil
    }
    

    playground example