Given the following definitions:
type Collector[T, C any] interface {
Collect(T, C) C
}
type mapCollector[K comparable, V any] struct {
GetKey func(result V) K
}
func (m *mapCollector[K, V]) Collect(value V, c *sync.Map) *sync.Map {
c.Store(m.GetKey(value), value)
return c
}
I am trying to write a templated make function for mapCollector
.
This does not work
func MakeUserMapCollector[K UserId, V User]() *mapCollector[K, V] {
c := mapCollector[K, V]{
GetKey: func(user V) K {
return user.getId()
}
}
return &c
}
Instead I have to be repetitive
func MakeUserMapCollector() *mapCollector[UserId, User] {
c := mapCollector[UserId, User]{
GetKey: func(user User) UserId {
return user.getId()
}
}
}
Is there a way to reuse the MakeUserMapCollector
type parameters to declare types in the function?
CodePudding user response:
You can create a generic constructor function that accepts a function for "collection" and then passes it to your mapCollector
struct.
That would look something like this:
func MakeUserMapCollector[K comparable, V any](collect func(result V) K) *mapCollector[K, V] {
return &mapCollector[K, V]{
GetKey: collect,
}
}
Then you can call the constructor function with your types as type parameters and your "collection" function:
mc := MakeUserMapCollector[UserId, User](func(result User) UserId { return result.GetId() })
Full example (Go Playground):
package main
import (
"fmt"
)
type mapCollector[K comparable, V any] struct {
GetKey func(result V) K
}
func (m mapCollector[K, V]) Collect(result V) K {
return m.GetKey(result)
}
type UserId string
type User struct {
Id UserId
}
func (u User) GetId() UserId {
return u.Id
}
func MakeUserMapCollector[K comparable, V any](collect func(result V) K) *mapCollector[K, V] {
return &mapCollector[K, V]{
GetKey: collect,
}
}
func main() {
u := User{
Id: "12",
}
mc := MakeUserMapCollector[UserId, User](func(result User) UserId { return result.GetId() })
fmt.Println(mc.Collect(u))
}