Дженерики на Голанге

Опубликовано: 22 Февраля, 2023

Обобщения — это, по сути, код шаблона/шаблона, написанный в форме для использования на Go с типами, которые можно добавить позже. Основная цель дженериков — добиться большей гибкости с точки зрения написания кода с добавлением меньшего количества строк. Концепция Generics существует уже давно и является частью многих языков программирования, включая Java, Python и C#, и это лишь некоторые из них.

По словам Александра Степанова, дженерики — это способ создания инкрементного источника каталогов абстрактного кода, который может быть либо функциями, либо алгоритмами, либо структурами данных. Как часть выпуска 1.18, Generics впервые были представлены в Golang.

Введите параметры в Go

Принимая во внимание типы и функции, Golang предлагает обобщения, используя концепцию, называемую параметрами типа. Эти типы параметров могут использоваться как с функциями, так и со структурами. Давайте углубимся в реализацию на нескольких примерах.

Мы начнем с написания шаблонного кода:

Go




package main
      
func main() {
    
    var radius1 int = 8
    var radius2 float = 9.5
}

Приведенный выше код объявляет две переменные типа int и float в основной функции, которые содержат значения двух радиусов некоторых окружностей. На следующем шаге мы объявим универсальную функцию, которая будет принимать любой из входных данных в зависимости от его типа и возвращать нам длину окружности.

Go




func generic_circumference [r int | float ](radius r) {
c= 2*3.14*r
fmt.println("The circumference is: ",c)
}

Итак, весь наш код будет выглядеть примерно так:

Go




package main
  
import "fmt"
  
func generic_circumference[r int | float32](radius r) {
  
    c := 2 * 3 * radius
    fmt.Println("The circumference is: ", c)
  
}
  
func main() {
    var radius1 int = 8
    var radius2 float32 = 9.5
  
    generic_circumference(radius1)
    generic_circumference(radius2)
}

Выход:

The circumference is:  48
The circumference is:  57

Основным отличительным фактором в приведенном выше коде является то, как мы объявляем переменную r в списке и предоставляем список типов (int, flaot32), которые эта переменная может принимать в зависимости от аргументов, передаваемых во время вызова функции.

Параметризованные типы в Go

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

Go




type Radius interface {
    int64 | int8 | float64
}
  
func generic_circumference[R Radius](radius r){  
    var c R
    c := 2 * 3 * radius
    fmt.Println("The circumference is: ", c)
}

В этом подходе мы сначала объявляем интерфейс с именем Radius, который содержит типы, которые мы можем передать функции, в приведенном выше примере это: int64, int8 и float64 . Следующее изменение заключается в том, как мы объявляем нашу общую функцию. В объявлении функции, используя квадратные скобки, мы передаем экземпляр этого интерфейса, который мы объявили выше.

R используется в приведенном выше примере для обозначения любого из типов, поддерживаемых интерфейсом Radius. Если мы вызываем generic_circumferenc e со значением float64, то R в контексте этой функции является значением типа float64, если мы вызываем функцию с int64, то R имеет значение int64 и так далее.

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

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