How to create generic extension method for a generic slice in golang

You have to declare the slice type with type parameters you want to use for the Map() (or for any other) method:

type slice[E, V any] []E

And you have to add the type parameters to the receiver, without the constraints (those will be the same as defined at the type declaration), as if you'd instantiate the generic slice type:

func (s *slice[E, V]) Map(iteratee func(E) V) *[]V {
    result := []V{}
    for _, item := range *s {
        result = append(result, iteratee(item))
    }

    return &result
}

Testing it:

s := slice[int, string]{1, 2, 3}
m := s.Map(func(i int) string { return fmt.Sprint("x", i) })
fmt.Println(m)

Which will output (try it on the Go Playground):

&[x1 x2 x3]

Also note that slices (slice headers) already contain a pointer to an underlying array, so it's rare that you need to use a pointer to slice. Instead declare the method with non-pointer receiver, and return a non-pointer (try this one on the Go Playground):

func (s slice[E, V]) Map(iteratee func(E) V) []V {
    result := []V{}
    for _, item := range s {
        result = append(result, iteratee(item))
    }

    return result
}

Relevant section from the (tip) spec: Spec: Method declarations:

If the receiver base type is a parameterized type, the receiver specification must declare corresponding type parameters for the method to use. This makes the receiver type parameters available to the method.

Syntactically, this type parameter declaration looks like an instantiation of the receiver base type, except that the type arguments are the type parameters being declared, one for each type parameter of the receiver base type. The type parameter names do not need to match their corresponding parameter names in the receiver base type definition, and all non-blank parameter names must be unique in the receiver parameter section and the method signature. The receiver type parameter constraints are implied by the receiver base type definition: corresponding type parameters have corresponding constraints.


Then I want to make this method as an extension method of slice

You can't do this with or without generics. You can only declare methods on defined types (i.e. types with identifiers), and in your second snippet, E is not a defined type, it's a type parameter.

Furthermore, unlike Javascript where all arrays inherit the Array prototype, a slice type, in itself, in Go isn't defined either. As a matter of fact, it's formalized in the language specs as:

SliceType = "[" "]" ElementType .

As you can see there's no identifier in this spec. So you can't declare a method on any and all slices, because there isn't a catch-all type that can be the receiver for such method.

You can declare methods on defined slice types, and those can be parametrized.

But in order to use the second type param V, it must be defined on the type declaration. Methods are not permitted to have type params not specified on the receiver type. For example:

// type def: must specify V here
type Slice[T, V any] []T

func (s Slice[T,V]) Map(iteratee func(T) V) []V {
    result := make([]V, 0)
    for _, item := range s {
        result = append(result, iteratee(item))
    }

    return result
}

But at this point, you might as well keep using a generic function, that has the advantage of permitting type inference, thus allowing you to have less verbose code and omit explicit type params during the instantiation.

Playground showing method vs func: https://gotipplay.golang.org/p/R7uAq0SBUjj