Как использовать дженерики Golang со структурами
Начиная с версии Go 1.18 у нас наконец появилась сила дженериков. На этой неделе, когда я просматривал исходный код Golang, я нашел пример того, как создавать структуры с помощью дженериков.
В этом посте я покажу вам, как это сделать.
Прежде чем мы начнем, давайте предположим, что мы реализуем систему блогов с двумя перечисленными ниже структурами.
package blog
type Category struct {
ID int32
Name string
Slug string
}
type Post struct {
ID int32
Categories []Category
Title string
Description
Slug string
}
В поисках некоторого повышения производительности мы реализуем систему кэширования, которая гарантирует, что никто не сможет изменить какие-либо данные непосредственно внутри кэша.
Имея в виду эти спецификации, давайте создадим новый пакет с именем cache
.
Этому пакету нужна частная структура для хранения всех данных, которые мы хотим кэшировать. Но прежде чем мы создадим эту структуру, давайте создадим интерфейс для типов, которые будут кэшироваться.
package cache
type cacheable interface {
blog.Category | blog.Post
}
Хорошо! Теперь мы можем создать нашу частную и общую структуру для хранения данных.
type cache[T cacheable] struct {
data[string]T
}
Чтобы манипулировать данными, мы реализуем два метода: Set
и Get
.
func (c *cache[T]) Set(key string, value T) {
c.data[key] = value
}
func (c *cache[T]) Get(key string) (v T) {
if v, ok := c.data[key]; ok {
return v
}
return
}
Теперь давайте добавим общую функцию для создания и возврата указателя на новый кеш.
func New[T cacheable]() {
c := cache[T]{}
c.data = make(map[string]T)
return &c
}
Чтобы использовать наш пакет, все, что нам нужно сделать, это создать новый кеш для типа, который мы хотим кэшировать, и использовать методы структуры, как в примере ниже.
func main() {
// create a new category
category := blog.Category{
ID: 1,
Name: "Go Generics",
Slug: "go-generics",
}
// create cache for blog.Category struct
cc := cache.New[blog.Category]()
// add category to cache
cc.Set(category.Slug, category)
// create a new post
post := blog.Post{
ID: 1,
Categories: []blog.Category{
{ID: 1, Name: "Go Generics", Slug: "go-generics"},
},
Title: "Generics in Golang structs",
Text: "Here go's the text",
Slug: "generics-in-golang-structs",
}
// create cache for blog.Post struct
cp := cache.New[blog.Post]()
// add post to cache
cp.Set(post.Slug, post)
}