Материал проходит вычитку — возможны неточности.
Урок 61 из 118

Ограничения

Кэш метаданных отказался принимать произвольные ключи: компилятор требовал comparable. Для чисел Миша собрал union-ограничение, и после пары отказов код всё же собрался. Разбор ограничений занял вторую половину дня.

Главная мысль

ограничение типа решает, что можно делать с T: any не разрешает типоспецифичные операции (==, +, методы), comparable — сравнивать, свой интерфейс — методы, а union с тильдой (~int | ~int64) — арифметику над семействами типов.

Comparable

func contains[T comparable](s []T, v T) bool {
    for _, x := range s {
        if x == v {
            return true
        }
    }
    return false
}

any допускает любой тип, но внутри функции про T почти ничего не известно — сравнение x == v не скомпилировалось бы. Встроенное comparable требует, чтобы тип можно было сравнивать через ==.

Union для арифметики

comparable не даёт операций <, >, +. Для них нужно своё ограничение — интерфейс, перечисляющий типы:

type Number interface {
    int | int64 | float64
}

func sum[T Number](s []T) T {
    var total T
    for _, x := range s {
        total += x
    }
    return total
}

Запись int | int64 | float64 — union, объединение типов. Ограничение может быть и обычным интерфейсом с методами: тогда T обязан реализовывать перечисленные методы.

Тильда ~

type Ordered interface {
    ~int | ~int64 | ~float64
}

type MyInt int // underlying type — int

func max[T Ordered](a, b T) T {
    if a > b {
        return a
    }
    return b
}

max(MyInt(1), MyInt(2)) // работает благодаря ~

Без ~ ограничение int не приняло бы MyInt, хотя под капотом это тот же int. Тильда говорит: «подходит любой тип, чей underlying type — из списка». В «Полке» это пригодилось для собственных типов вроде размера файла, объявленных поверх int64.

В следующем уроке

Вы узнаете:

  • почему ~int | fmt.Stringer не компилируется
  • почему constraints.Ordered переехал в cmp
Задание · вопросы

Проверьте себя

Вопрос 1 из 3

Что разрешает ограничение comparable в дженериках?

Вопрос 2 из 3

Зачем нужна тильда ~ в ограничении ~int?

Вопрос 3 из 3

Что такое union-ограничение int | int64 | float64?

Итоги

Ограничение — контракт на T: comparable для ==, union для арифметики, интерфейс для методов, ~ для семейств с общим underlying type.

Наш сайт собирает куки. Чтобы тебе было удобнее им пользоваться. Нажимая на кнопку, ты даёшь разрешение собирать куки