🤔 Какие есть способы написания обобщенного кода?



Существует несколько способов написания обобщенного кода. До выхода Go 1.18, который представил встроенную поддержку обобщений (generics), разработчики использовали различные техники для достижения аналогичного эффекта.



🚩Подходы



🟠Параметризованные типы (Generics) в Go 1.18+

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

package main



import "fmt"



func Map[T any](arr []T, f func(T) T) []T {

result := make([]T, len(arr))

for i, v := range arr {

result[i] = f(v)

}

return result

}



func main() {

nums := []int{1, 2, 3, 4}

doubled := Map(nums, func(n int) int { return n * 2 })

fmt.Println(doubled) // [2, 4, 6, 8]

}




Пример обобщенного типа:

package main



import "fmt"



type Pair[T any, U any] struct {

First T

Second U

}



func main() {

p := Pair[int, string]{First: 1, Second: "one"}

fmt.Println(p) // {1 one}

}




🟠Использование интерфейсов

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

package main



import "fmt"



type Stringer interface {

String() string

}



func Print(s Stringer) {

fmt.Println(s.String())

}



type Person struct {

Name string

}



func (p Person) String() string {

return p.Name

}



func main() {

p := Person{Name: "Alice"}

Print(p) // Alice

}




🟠Пустые интерфейсы (`interface{}`)

Пустой интерфейс (interface{}) может содержать значения любого типа. Это позволяет создавать функции, принимающие значения любых типов, но требует явного приведения типов.

package main



import "fmt"



func Print(v interface{}) {

fmt.Println(v)

}



func main() {

Print(42)

Print("Hello")

Print([]int{1, 2, 3})

}




🟠Рефлексия (Reflection)

Рефлексия позволяет программам исследовать и изменять структуру и поведение объектов во время выполнения. Это мощный, но сложный способ написания обобщенного кода.

package main



import (

"fmt"

"reflect"

)



func Print(v interface{}) {

rv := reflect.ValueOf(v)

fmt.Println("Type:", rv.Type(), "Value:", rv)

}



func main() {

Print(42) // Type: int Value: 42

Print("Hello") // Type: string Value: Hello

Print([]int{1, 2, 3}) // Type: []int Value: [1 2 3]

}




Ставь 👍 и забирай 📚 Базу знаний