TGViewer
Библиотека Go-разработчика | Golang Библиотека Go-разработчика | Golang @goproglib · 24.1K subscribers
Post #7176 2.92K
💡 Дженерики в Go. Полезные функции и стандартная библиотека

Посмотрим на практические функции, которые упрощают повседневную работу со слайсами и мапами. А также на то, что Go уже включает из коробки в пакетах slices и maps.

Map, Filter, Reduce

Go не предоставляет эти функции в стандартной библиотеке, но с дженериками их легко написать самостоятельно.

Map трансформирует каждый элемент слайса:
func Map[T, U any](slice []T, fn func(T) U) []U {
result := make([]U, len(slice))
for i, v := range slice {
result[i] = fn(v)
}
return result
}


Filter оставляет только элементы, подходящие под условие:
func Filter[T any](slice []T, predicate func(T) bool) []T {
var result []T
for _, v := range slice {
if predicate(v) {
result = append(result, v)
}
}
return result
}


Reduce сворачивает слайс в одно значение:
func Reduce[T, U any](slice []T, initial U, fn func(U, T) U) U {
result := initial
for _, v := range slice {
result = fn(result, v)
}
return result
}


Пример использования всех трёх вместе:
numbers := []int{1, 2, 3, 4, 5}

doubled := Map(numbers, func(n int) int { return n * 2 })
// [2, 4, 6, 8, 10]

evens := Filter(numbers, func(n int) bool { return n%2 == 0 })
// [2, 4]

sum := Reduce(numbers, 0, func(acc, n int) int { return acc + n })
// 15


Keys и Values для map

Ещё одна частая задача, получить ключи или значения мапы отдельным слайсом:
func Keys[K comparable, V any](m map[K]V) []K {
keys := make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}


Аналогично для значений. Порядок не гарантирован, как и при обычной итерации по map в Go.

Дженерик-кеш

Потокобезопасный кеш на дженериках. Полезная штука для сервисов, где нужно кешировать объекты разных типов:
type Cache[K comparable, V any] struct {
mu sync.RWMutex
items map[K]V
}

func NewCache[K comparable, V any]() *Cache[K, V] {
return &Cache[K, V]{items: make(map[K]V)}
}

func (c *Cache[K, V]) Get(key K) (V, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
val, ok := c.items[key]
return val, ok
}

func (c *Cache[K, V]) Set(key K, value V) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[key] = value
}


Вместо map[string]interface{} с приведением типов получаем типобезопасный контейнер. Компилятор ловит ошибки за вас.

Пакеты slices и maps

Начиная с Go 1.21, стандартная библиотека включает пакеты slices и maps с готовыми дженерик-функциями.

Прежде чем писать свои утилиты, стоит заглянуть сюда:
import (
"slices"
"maps"
)

numbers := []int{3, 1, 4, 1, 5, 9}

slices.Sort(numbers)
slices.Contains(numbers, 4) // true
slices.Index(numbers, 4) // позиция элемента
slices.Max(numbers) // 9
slices.Min(numbers) // 1
slices.Reverse(numbers)


Для сортировки с кастомной функцией сравнения есть slices.SortFunc:
slices.SortFunc(numbers, func(a, b int) int {
return b - a // по убыванию
})


Пакет maps предлагает Clone, Equal и DeleteFunc:
m := map[string]int{"a": 1, "b": 2}
copy := maps.Clone(m)
maps.DeleteFunc(m, func(k string, v int) bool {
return v < 2
})


Для получения ключей и значений в виде слайсов используется связка maps.Keys / maps.Values с slices.Collect:
keys := slices.Collect(maps.Keys(m))
vals := slices.Collect(maps.Values(m))


Практические советы

Используйте дженерики, когда у вас действительно есть дублирование кода для разных типов. Если функция работает только с одним типом, дженерики не нужны.

Выбирайте максимально точный constraint. comparable вместо any, если нужно сравнение. cmp.Ordered вместо comparable, если нужны операторы < и >.

Дженерики в Go не пытаются заменить всю систему типов. Это точечный инструмент для устранения дублирования.

Вместе с пакетами slices и maps они закрывают большинство задач, которые раньше решались через interface{}, рефлексию или генерацию кода.

📍 Навигация: Вакансии • Задачи • Собесы

🐸 Библиотека Go-разработчика

#GoDeep
  • 👍 13
  • ❤ 2
More from @goproglib
  1. Sep 30, 2026🧑‍💻 Эмулятор AWS-сервисов Kumo — это небольшой инструмент на Go для локальной имитации A…
  2. Sep 29, 2026👨‍💻 Библиотека для написания LSP-серверов Написать свой Language Server с нуля на Go сло…
  3. Sep 28, 2026🤔 Вопрос с собеседования по Go Что выведет программа? ❤️ — 1 true / 0 false 🔥 — 1 true /…
  4. Sep 28, 2026👩‍💻 Что на самом деле происходит внутри Go map? После Go 1.24 обычный map внутри работае…
  5. Sep 26, 2026🔥 В Go 1.27 появился portable SIMD До этого SIMD-оптимизации в Go требовали архитектурног…
  6. Sep 25, 2026🤡🤡 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека Go-разработчика #GoGiggle
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →