Схожие структуры с разными типами данных, как избежать дублирования кода?

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

1) Использование интерфейсов: Интерфейсы позволяют объявить набор методов, которые должны быть реализованы конкретными типами данных. Вы можете создать интерфейс, описывающий общие методы для схожих структур, и затем реализовывать этот интерфейс для каждого конкретного типа данных. Таким образом, вы сможете вызывать общие методы для разных типов данных.

Пример:

type Shape interface {
    Area() float64
    Perimeter() float64
}

type Rectangle struct {
    width  float64
    height float64
}

func (r Rectangle) Area() float64 {
    return r.width * r.height
}

func (r Rectangle) Perimeter() float64 {
    return 2*r.width + 2*r.height
}

type Circle struct {
    radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.radius * c.radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.radius
}

func main() {
    r := Rectangle{width: 3, height: 4}
    c := Circle{radius: 5}
    
    shapes := []Shape{r, c}
    
    for _, shape := range shapes {
        fmt.Println("Area:", shape.Area())
        fmt.Println("Perimeter:", shape.Perimeter())
    }
}

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

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

3) Использование наследования и встраивания структур: В Go нет классического наследования, но вы можете использовать встраивание структур для создания связей между схожими структурами. Вы можете создать базовую структуру, содержащую общие поля и методы, и затем встраивать эту структуру в другие структуры, чтобы унаследовать её функциональность.

Пример:

type BaseShape struct {
    // Общие поля
}

func (s *BaseShape) Area() float64 {
    // Общая реализация метода
}

func (s *BaseShape) Perimeter() float64 {
    // Общая реализация метода
}

type Rectangle struct {
    BaseShape  // Встраивание базовой структуры
    width  float64
    height float64
}

type Circle struct {
    BaseShape  // Встраивание базовой структуры
    radius float64
}

func main() {
    r := Rectangle{width: 3, height: 4}
    c := Circle{radius: 5}
    
    fmt.Println("Rectangle Area:", r.Area())
    fmt.Println("Rectangle Perimeter:", r.Perimeter())
    
    fmt.Println("Circle Area:", c.Area())
    fmt.Println("Circle Perimeter:", c.Perimeter())
}

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