Interface/Implementation Simultaneity in Golang Generics
Consider the task of creating a generic function to fill a slice with initialized values. While this may seem straightforward, challenges arise when attempting to utilize slices of interfaces and specify concrete types within the function.
In Go 1.18, constraining both X and Y as any types within the generic function Fill leads to a loss of any relationship between the interface and its implementors. This prevents the assignment of instances of Y to slice[i] within the function.
To overcome this, 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 approach panics when Y does not implement X. Additionally, using a pointer type for Y results in the loss of information about the base type and a nil baseline value.
To address these issues, it is recommended to use a constructor function instead of a 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>
This approach effectively fills the slice with initialized values created by the constructor function, providing a more robust and flexible solution to the problem.
The above is the detailed content of **How to Preserve Interface-Implementor Relationships When Using Generics in Go for Slice Initialization?**. For more information, please follow other related articles on the PHP Chinese website!