嵌套泛型类型:重用函数的类型参数

huangapple go评论75阅读模式
英文:

Nested generic types: Reuse function's Type parameter

问题

给定以下定义:

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
}

我正在尝试为mapCollector编写一个模板化的make函数。
这个不起作用:

func MakeUserMapCollector[K UserId, V User]() *mapCollector[K, V] {
    c := mapCollector[K, V]{
        GetKey: func(user V) K {
            return user.getId()
        }
    }
    return &c
}

相反,我必须重复一遍:

func MakeUserMapCollector() *mapCollector[UserId, User] {
    c := mapCollector[UserId, User]{
        GetKey: func(user User) UserId {
            return user.getId()
        }
    }
}

有没有办法重用MakeUserMapCollector的类型参数来在函数中声明类型?

英文:

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?

答案1

得分: 2

你可以创建一个通用的构造函数,该函数接受一个用于"collection"的函数,并将其传递给你的mapCollector结构体。

代码如下所示:

func MakeUserMapCollector[K comparable, V any](collect func(result V) K) *mapCollector[K, V] {
	return &mapCollector[K, V]{
		GetKey: collect,
	}
}

然后,你可以使用你的类型作为类型参数以及你的"collection"函数调用构造函数:

mc := MakeUserMapCollector[UserId, User](func(result User) UserId { return result.GetId() })

完整示例(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))
}
英文:

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))
}

huangapple
  • 本文由 发表于 2022年9月27日 02:02:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/73858175.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定