Home >Backend Development >Golang >How to Fill a Slice of Interfaces with Concrete Types in Golang Generics?
In Go 1.18, generics have introduced new possibilities for type handling. However, certain scenarios may pose challenges when using interfaces and concrete types together.
One such scenario arises when attempting to create a function like this:
<code class="go">func Fill[X any](slice []*X){ for i := range slice { slice[i] = new(X) } }</code>
This function is meant to fill a slice of interfaces with concrete types. For instance, an array of *int can be filled with new(int) using this function.
The issue arises when trying to fill a slice of interfaces with a concrete type that implements the interface. Consider this code:
<code class="go">func Fill[X, Y any](slice []X){ for i := range slice { slice[i] = new(Y) // not work! } } xs := make([]sync.Locker, 10) // fill with nils Fill[sync.Locker,sync.Mutex](xs) // ouch</code>
In this case, the function does not work because constraining both X and Y to any breaks the relationship between the interface and the implementing type. The compiler only recognizes that X and Y are distinct types at compile time.
There is a workaround to make the code compile using an explicit assertion:
<code class="go">func Fill[X, Y any](slice []X) { for i := range slice { slice[i] = any(*new(Y)).(X) } }</code>
However, this solution has a significant drawback: it panics if Y does not implement X, like with sync.Locker and sync.Mutex. Additionally, using a pointer type for Y results in nil values since it loses the base type and zero value information.
A more robust solution is to use a constructor function instead of the second type parameter:
<code class="go">func main() { xs := make([]sync.Locker, 10) Fill(xs, func() sync.Locker { return &sync.Mutex{} }) } func Fill[X any](slice []X, f func() X) { for i := range slice { slice[i] = f() } }</code>
In this approach, the function takes a slice of type X and a constructor function. The constructor function creates an instance of type X, filling the slice with concrete instances.
The above is the detailed content of How to Fill a Slice of Interfaces with Concrete Types in Golang Generics?. For more information, please follow other related articles on the PHP Chinese website!