Примеры дженериков Golang

Primery Dzenerikov Golang



Функция дженериков Golang позволяет создавать многоразовый код, безопасный по типам и совместимый с широким спектром типов. К счастью, добавление дженериков в Go открывает новые возможности для повторного использования кода и гибкости. В последней версии Golang появилась долгожданная поддержка дженериков.

Что еще более важно, дженерики поддерживают строгую безопасность типов Go, которая обеспечивает статическую проверку типов во время компиляции и гарантирует правильность типов. Они обеспечивают стандартизированную обработку ошибок в универсальном коде, что повышает ясность и удобство сопровождения. Кроме того, они обеспечивают стандартизированную обработку ошибок в общем коде, что повышает ясность и удобство сопровождения. В этом посте мы рассмотрим несколько реальных приложений и примеров дженериков Go.

Пример 1: Использование универсальной функции Golang

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







упаковка основной
Импортировать 'ФМТ'
функция длина окружности [ р инт | поплавок32 ]( радиус г ) {
с '=' 3 * 2 * радиус
ФМТ . Распечатать ( «Общая окружность:» , с )
}
функция основной () {
был г1 инт '=' 7
был г2 поплавок32 '=' 7 . 5
длина окружности ( г1 )
длина окружности ( г2 )
}

В начале предыдущего кода строка импортирует пакет «fmt», который предоставляет функции для форматированного ввода-вывода, включая вывод вывода на консоль. Затем мы определяем общую функцию с именем «circumference», которая принимает радиус параметра общего типа «r», который может быть либо «int», либо «float32». Внутри функции он вычисляет длину окружности, умножая радиус на постоянное значение «3», а затем умножая его на «2». Наконец, он печатает рассчитанную длину окружности с помощью «fmt.Println».



Далее у нас есть основная функция, в которой объявляются две переменные, r1 и r2, которым присваиваются значения 7 и 7,5 соответственно. После этого функция «окружность» вызывается дважды, передавая r1 и r2 в качестве аргументов.



Вывод отображает расчет путем печати окружностей кругов следующим образом:





Пример 2. Использование универсального интерфейса Golang

Более того, дженерики Golang помогают нам своими интерфейсами. Интерфейсы в Go — жизненно важный инструмент для облегчения повторного использования кода и полиморфизма. Позволяя им работать со многими типами, дженерики увеличивают мощность интерфейсов. Ниже приведен исходный код интерфейса дженериков Golang:



упаковка основной
Импортировать 'ФМТ'
тип Эмпаж интерфейс {
int64 | int32 | поплавок32 | поплавок64
}
функция новыйGenericFunc [ возраст Возраст ]( emp_Age возраст ) {
вал '=' инт ( emp_Age ) + 1
ФМТ . Распечатать ( вал )
}
функция основной () {
ФМТ . Распечатать ( «Возраст сотрудников» )
был Возраст1 int64 '=' 24
был Возраст2 поплавок64 '=' 25 . 5
новыйGenericFunc ( Возраст1 )
новыйGenericFunc ( Возраст2 )
}

В предыдущем исходном коде мы определили интерфейс с именем «EmpAge», который указывает возможные типы для возраста сотрудника. Интерфейс включает типы int64, int32, float32 и float64. Этот интерфейс позволяет «универсальной» функции принимать любой из этих типов в качестве аргумента. После этого мы используем универсальную функцию с именем newGenericFunc, которая принимает параметр emp_Age универсального типа возраста, который может быть любым типом, удовлетворяющим интерфейсу EmpAge. Внутри функции он преобразует emp_Age в int и увеличивает его на 1, как показано.

Затем мы объявляем две переменные, Age1 и Age2, и присваиваем значения 24 и 25,5 соответственно в функции main. После этого Age1 и Age2 передаются в качестве параметров функции newGenericFunc, которая выполняется дважды. При этом возраст увеличивается на 1 и генерирует обновленные значения.

Вывод, который получается в следующем, представляет собой возраст из универсальной функции, которая использует интерфейс:

Пример 3: Использование общей структуры данных Golang

Кроме того, универсальные шаблоны Go также дают нам возможность создавать общие структуры данных, такие как стеки, очереди и связанные списки. Рассмотрим реализацию общего стека в следующем:

Импортировать 'ФМТ'
тип Куча [ любой ] [] Т
функция ( ул. * Куча [ Т ]) Толкать ( пункт Т ) {
ул. '=' добавить ( * ул. , элемент )
}
функция ( ул. * Куча [ Т ]) Поп () Т {
если только ( * ул. ) == 0 {
паника ( «Ничего в стеке» )
}
индекс '=' только ( * ул. ) - 1
элемент '=' ( * ул. )[ индекс ]
* ул. '=' ( * ул. )[: индекс ]
возвращаться элемент
}
функция основной () {
куча '=' новый ( Куча [ инт ])
куча . Толкать ( 1 )
куча . Толкать ( 2 )
куча . Толкать ( 3 )
ФМТ . Распечатать ( куча . Поп ())
ФМТ . Распечатать ( куча . Поп ())
ФМТ . Распечатать ( куча . Поп ())
}

В предыдущем коде определен общий тип под названием «Стек», который представляет стек. Заполнитель «T» позволяет стеку хранить элементы любого типа. Тип «Стек» реализован как срез элементов типа «Т». Здесь развернуты две функции для типа «Стек»: «Push» и «Pop». Функция Push() отвечает за добавление элементов в стек. Он принимает элемент аргумента типа «T» и добавляет его к базовому срезу с помощью функции append().

Хотя функция Pop() берет начальный компонент из стека и возвращает его, она сначала определяет, пуст ли стек, оценивая размер лежащего в основе среза. Уведомление об ошибке отправляется, если стек кажется пустым, что вызывает панику. В противном случае он извлекает последний элемент из среза, удаляет его из стека, разрезая срез до предпоследнего элемента, и возвращает удаленный элемент.

Затем создается новый стек целых чисел с использованием синтаксиса Stack[int] в основной функции этого кода. После этого трижды вызывается метод «Push», чтобы добавить в стек целые числа 1, 2 и 3. Тем не менее, метод Pop вызывается три раза для извлечения и печати элементов из стека.

Следующий вывод показывает, что элементы удаляются из стека в обратном порядке:

Пример 4: Использование общих ограничений Golang

Go также предлагает настраиваемые ограничения, которые обеспечивают большую гибкость и определяют конкретные требования к универсальным конструкциям в зависимости от потребностей их приложений. Код настраиваемых универсальных ограничений приведен для демонстрации ниже:

упаковка основной
Импортировать 'ФМТ'
тип Числа интерфейс {
int64 | поплавок64
}
функция основной () {
Плавающее значение '=' [] поплавок64 { 2 . 0 , 4 . 0 , 6 . 0 , 8 . 0 , 10 . 0 }
Целое значение '=' [] int64 { 2 , 4 , 6 , 8 , 10 }
сумма1 '=' общая сумма ( Плавающее значение )
сумма2 '=' общая сумма ( Целое значение
ФМТ . Распечатать ( 'Сумма float64:' , сумма1 )
ФМТ . Распечатать ( 'Сумма int64:' , сумма2 )

}
функция общая сумма [ п Числовые ]( числа [] н ) н {
был Я н
для _ , на одной '=' диапазон числа {
сумма += на одной
}
возвращаться сумма
}

В предыдущем исходном коде мы определяем интерфейс Numerics с помощью метода «Sum». Затем мы создаем два пользовательских типа, «FloatValue» и «IntegerValue», которые реализуют интерфейс Numerics, предоставляя соответствующие методы «Sum». Функция genericSum теперь может принимать срезы любого типа, удовлетворяющего числовому интерфейсу. Внутри функции мы перебираем элементы и вызываем метод «Сумма» для вычисления суммы. Наконец, в основной функции мы создаем срезы FloatValue и IntegerValue и передаем их функции genericSum(), которая правильно вычисляет сумму элементов в каждом срезе.

Ожидаемый результат теперь виден на следующем экране:

Заключение

Мы рассмотрели несколько практических примеров универсальных шаблонов Go, которые включают создание универсальной структуры данных и универсальной функции, определение универсального интерфейса и использование ограничения пользовательского типа. Эти примеры демонстрируют мощь и гибкость, которые дженерики привносят в язык программирования Go. Обратите внимание, что генерация универсального кода во время компиляции обеспечивает эффективный размер двоичного файла и время компиляции.