In Go 1.18, generics allow developers to define functions and data structures that operate on a wider range of types. However, a specific scenario has emerged where users seek to use generics with interfaces while also providing a concrete type for generic type parameters.
Consider the following function that aims to populate a slice with new instances of a concrete type:
<code class="go">func Fill[X any](slice []*X) { for i := range slice { slice[i] = new(X) } }</code>
This function works as expected when filling a slice of pointers to a specific type, such as []*int. However, if the slice consists of interfaces and the function is called with a concrete type for the generic parameter, compilation fails.
<code class="go">xs := make([]sync.Locker, 10) // fill with nils Fill[sync.Locker,sync.Mutex](xs) // ouch</code>
The issue arises because constraining both type parameters X and Y to any removes the relationship between the interface and its concrete implementation. At compile time, it is only known that X and Y are distinct types.
To address this problem, an explicit assertion can be used:
<code class="go">func Fill[X, Y any](slice []X) { for i := range slice { slice[i] = any(*new(Y)).(X) } }</code>
However, this solution introduces potential runtime panics if Y does not implement X. Moreover, if Y is a pointer type, the base type information is lost, resulting in nil values instead of instances of the desired concrete type.
A better approach is to use a constructor function instead of a second generic parameter, as demonstrated below:
<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>
This solution provides a more robust and idiomatic way to fill a slice with instances of a specific concrete type while maintaining type safety.
The above is the detailed content of How to Fill a Slice with Concrete Implementations Using Golang Generics and Interfaces?. For more information, please follow other related articles on the PHP Chinese website!