Skip to content

proposal: maps: add KeysSlice and ValuesSlice functions to extract map contents as slices #73291

Closed as duplicate of#61626
@samsonkolge

Description

@samsonkolge

Proposal Details

Background

The maps package currently provides iterator-based functions (Keys and Values)
that return iterators over a map's keys or values. While iterators are powerful
and composable, they require extra code to convert to slices, which is a common
use case.

Converting map keys or values to slices is a recurring pattern in Go code.
Currently, developers need to write boilerplate like:

keys := make([]KeyType, 0, len(myMap))
for k := range myMap {
    keys = append(keys, k)
}

Proposal

Add two new functions to the maps package:

  1. KeysSlice[M ~map[K]V, K comparable, V any](m M) []K
  2. ValuesSlice[M ~map[K]V, K comparable, V any](m M) []V

These functions would extract map keys/values into slices, complementing the
existing iterator-based functions and providing a direct solution for the common
use case of converting map contents to slices.

Proposed Implementation

The implementation would be straightforward:

// KeysSlice returns a new slice containing the keys of m.
// The keys will be in an indeterminate order.
func KeysSlice[M ~map[K]V, K comparable, V any](m M) []K {
    r := make([]K, 0, len(m))
    for k := range m {
        r = append(r, k)
    }
    return r
}

// ValuesSlice returns a new slice containing the values of m.
// The values will be in an indeterminate order.
func ValuesSlice[M ~map[K]V, K comparable, V any](m M) []V {
    r := make([]V, 0, len(m))
    for _, v := range m {
        r = append(r, v)
    }
    return r
}

Use Cases

These functions would be useful for various common scenarios:

  1. Working with map keys in a sorted manner:

    keys := maps.KeysSlice(myMap)
    slices.Sort(keys)
    // Process keys in sorted order
  2. Getting a list of values for processing:

    values := maps.ValuesSlice(userRoles)
    for _, role := range values {
        // Process roles
    }
  3. Converting to a different representation:

    // Easily convert map values to a slice for API responses
    response.Items = maps.ValuesSlice(dataMap)

Alternatives Considered

  1. Using existing iterator functions:
    While Keys() and Values() combined with slices.Collect() can achieve
    similar functionality, this requires importing multiple packages and is less
    discoverable for users:

    keys := slices.Collect(maps.Keys(myMap))
  2. Using range with assignment:
    The current approach of manually creating slices and iterating is verbose and
    requires boilerplate code.

Compatibility

This change adds new functionality without modifying existing behavior, so it has
no compatibility concerns.

/cc @golang/maps-owners

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions