diff --git a/src/reflect/value.go b/src/reflect/value.go index 49bd0a10..e8835806 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -641,7 +641,27 @@ func (v Value) OverflowFloat(x float64) bool { } func (v Value) MapKeys() []Value { - panic("unimplemented: (reflect.Value).MapKeys()") + if v.Kind() != Map { + panic(&ValueError{Method: "MapKeys", Kind: v.Kind()}) + } + + // empty map + if v.Len() == 0 { + return nil + } + + keys := make([]Value, 0, v.Len()) + + it := hashmapNewIterator() + k := New(v.typecode.Key()) + e := New(v.typecode.Elem()) + + for hashmapNext(v.pointer(), it, k.value, e.value) { + keys = append(keys, k.Elem()) + k = New(v.typecode.Key()) + } + + return keys } //go:linkname hashmapStringGet runtime.hashmapStringGetUnsafePointer diff --git a/src/reflect/value_test.go b/src/reflect/value_test.go index d9b4231d..668ffb01 100644 --- a/src/reflect/value_test.go +++ b/src/reflect/value_test.go @@ -86,6 +86,17 @@ func TestMap(t *testing.T) { t.Errorf("MapRange return unexpected keys: got %v, want %v", gotKeys, wantKeys) } + refMapKeys := mref.MapKeys() + gotKeys = gotKeys[:0] + for _, v := range refMapKeys { + gotKeys = append(gotKeys, v.Interface().(string)) + } + + sort.Strings(gotKeys) + if !equal(gotKeys, wantKeys) { + t.Errorf("MapKeys return unexpected keys: got %v, want %v", gotKeys, wantKeys) + } + mref.SetMapIndex(ValueOf("bar"), Value{}) if _, ok := m["bar"]; ok { t.Errorf("SetMapIndex failed to delete `bar`")