Урок объясняет, как работают generics в Go: синтаксис параметров типа, ограничения (constraints), приближённые типы, встроенные ограничения, создание собственных constraints и использование generics в структурах.
Generics --- это механизм, позволяющий писать функции и типы, которые работают с разными типами данных, без дублирования кода. Они обеспечивают гибкость, безопасность типов и универсальность решений.
func name[T constraint](value T) T {
// ...
}
Где:
T - параметр типаconstraint - набор допустимых типовВозможны несколько параметров типа:
func combine[T A | B, U C](a T, b U) {
// ...
}
func IsEqual[T comparable](a, b T) bool {
return a == b
}
IsEqual(2, 2)
IsEqual("foo", "bar")
IsEqual('a', 'b')
IsEqual[uint8](4, 4)
Ограничения создаются через интерфейсы:
type Integers32 interface {
int32 | uint32
}
func SumNumbers[T Integers32](arr []T) T {
var sum T
for i := 0; i < len(arr); i++ {
sum += arr[i]
}
return sum
}
Использование:
nums := []int32{1, 2, 3}
total := SumNumbers(nums)
type Integers32 interface {
int32 | uint32
}
type MyInt int32
nums := []MyInt{1,2,3}
// Ошибка: MyInt не входит в Integers32
Использование тильды (~) позволяет определять типы по их базовому
типу:
type Integers32 interface {
~int32 | ~uint32
}
Теперь MyInt на основе int32 будет работать.
Constraint Описание
any любой тип
comparable типы, поддерживающие == и !=
Integer все целые
Float числа с плавающей точкой
Complex все комплексные числа
Ordered типы, поддерживающие <, >
Generics также поддерживаются в структурах:
import "golang.org/x/exp/constraints"
type MyArray[T constraints.Ordered] struct {
inner []T
}
func (m *MyArray[T]) Max() T {
max := m.inner[0]
for i := 0; i < len(m.inner); i++ {
if m.inner[i] > max {
max = m.inner[i]
}
}
return max
}
Использование:
arr := MyArray[int]{inner: []int{6, 4, 8, 9, 4, 0}}
fmt.Println(arr.Max())
~ позволяет указывать приближённые типыconstraints содержит полезные ограничения