Issue
Coming from Nodejs, I could do something like:
// given an array `list` of objects with a field `fruit`:
fruits = list.map(el => el.fruit) # which will return an array of fruit strings
Any way to do that in an elegant one liner in golang?
I know I can do it with a range loop, but I am looking for the possibility of a one liner solution
Solution
In Go, arrays are inflexible (because their length is encoded in their type) and costly to pass to functions (because a function operates on a copy of its array arguments). I’m assuming you’d like to operate on slices rather than on arrays.
Because methods cannot take additional type arguments, you cannot simply declare a generic Map
method in Go. However, you can define Map
as a generic top-level function:
func Map[T, U any](ts []T, f func(T) U) []U {
us := make([]U, len(ts))
for i := range ts {
us[i] = f(ts[i])
}
return us
}
Then you can write the following code,
names := []string{"Alice", "Bob", "Carol"}
fmt.Println(Map(names, utf8.RuneCountInString))
which prints [5 3 5]
to stdout (try it out in this Playground).
Go 1.18 saw the addition of a golang.org/x/exp/slices
package, which provides many convenient operations on slices, but a Map
function is noticeably absent from it. The omission of that function was the result of a long discussion in the GitHub issue dedicated to the golang.org/x/exp/slices
proposal; concerns included the following:
- hidden cost (O(n)) of operations behind a one-liner
- uncertainty about error handling inside
Map
- risk of encouraging a style that strays too far from Go’s traditional style
Russ Cox ultimately elected to drop Map
from the proposal because it’s
probably better as part of a more comprehensive streams API somewhere else.
Answered By – jub0bs
Answer Checked By – Pedro (GoLangFix Volunteer)