Структури в Golang

У мові програмування Golang, структури відіграють ключову роль, слугуючи як один із найпоширеніших методів створення типів даних, які визначаються безпосередньо користувачем.

Ця стаття розкриє основи структур, показуючи, як ефективно їх використовувати у ваших розробках на Go, з підкріпленням різноманітними прикладами.

Розпочнімо нашу подорож у світ структур!

Вступ

Структура – це організована колекція полів даних, кожне з яких має свій визначений тип, об’єднаних в єдине ціле. Структури є незамінними, коли потрібно згрупувати пов’язані дані для створення комплексних записів. Структури можуть включати як вбудовані, так і користувацькі типи даних (сама структура також є типом, що визначається користувачем).

У Golang, структури є динамічними, що означає, що їх вміст можна змінювати протягом виконання програми.

Використання структур значно підвищує читабельність і підтримуваність коду, дозволяючи нам створювати і передавати складні набори даних між різними частинами програми. Уявіть, що вам потрібно передати десять параметрів у функцію – це швидко стане незручним. Структури тут приходять на допомогу, дозволяючи замінити передачу багатьох параметрів на передачу однієї структури.

Структура оголошується за допомогою ключових слів type та struct. Її опис міститься у фігурних дужках (подібно до класів в Java), де перераховуються поля з їх типами та іменами. Детальніше про це поговоримо у наступному розділі.

Якщо ви знайомі з об’єктно-орієнтованим програмуванням (ООП), можете думати про struct як про клас, але без можливості наслідування.

Оголошення структур

Тепер, коли ви зрозуміли концепцію структури та її призначення, час навчитися, як їх оголошувати. Базова схема структури виглядає так:

type назва_структури struct {
    поле1 тип_даних_поля1
    поле2 тип_даних_поля2
  }

Тут type та struct є зарезервованими словами, а структура визначається як сукупність полів з їхніми типами.

Розглянемо конкретний приклад:

package main

import (
  "fmt"
)

type User struct {
  name        string
  age         int
  bankBalance float32
}

func main() {
  var user User
  fmt.Println(user)
}

У цьому прикладі ми визначаємо структуру User, яка містить поля типу string, int і float32. У функції main() ми оголошуємо змінну user типу User та виводимо її. На виході ми отримаємо нульове значення структури, оскільки ми її ще не ініціалізували! Нульове значення – це значення за замовчуванням для кожного поля структури.

{ 0 0}

Ініціалізація структур

У попередньому розділі ми дізналися, як оголошувати структури. Тепер давайте розглянемо, як присвоювати їм початкові значення. Нижче наведено приклад коду, який демонструє цей процес:

package main

import (
  "fmt"
)

type User struct {
  name        string
  age         int
  bankBalance float32
}

func main() {
  // Ініціалізація з іменами полів
  user1 := User{
    name:        "Mohit",
    age:         24,
    bankBalance: 100.0,
  }
  
  // Ініціалізація без імен полів
  user2 := User{"Nidhi", 21, 1000.0}
  
  fmt.Println(user1)
  fmt.Println(user2)
}

Код демонструє два способи ініціалізації структури: з явним зазначенням імен полів та без них. Результатом виконання буде:

{Mohit 24 100}
 {Nidhi 21 1000}

Якщо при ініціалізації не вказано значення для деяких полів, то ці поля автоматично отримують нульові значення:

user1 := User{
    name:        "Mohit",
    age:         24,
  }

 // Вивід - { Mohit 24 0.0 }

Існує також інший спосіб створення структур, використовуючи ключове слово new. Розглянемо це далі.

Доступ до полів структури

Ми вже знаємо, як створювати та ініціалізувати структури. Тепер подивимося, як отримувати доступ до їхніх полів. Для цього в Golang використовується оператор крапки. На прикладі наведеного вище коду, давайте отримаємо доступ до полів name та age і виведемо їх значення:

package main

import (
  "fmt"
)

type User struct {
  name        string
  age         int
  bankBalance float32
}

func main() {
  // Ініціалізація з іменами полів
  user := User{
    name:        "Mohit",
    age:         24,
    bankBalance: 100.0,
  }

  fmt.Println(user.name)
  fmt.Println(user.age)
  fmt.Println(user.bankBalance)
}

Тут ми використовуємо ім'я_структури.ім'я_поля для доступу до полів структури. Результат виконання цього коду буде:

Mohit
 24
 100

Як згадувалося раніше, структури можна створювати за допомогою ключового слова new. Погляньмо, як це робиться:

user := new(User)
 user.name = "Mohit"
 user.age = 24
 user.bankBalance = 100.0

 fmt.Println(user)

 // Вивід - &{Mohit 24 100}

Ключове слово new повертає вказівник на щойно створену структуру. У Golang вам не потрібно явно розіменовувати вказівник, fmt.Println(*user) дасть той самий результат.

Вкладені структури

Структури в Golang можуть містити інші структури, створюючи таким чином вкладені структури.

package main

import (
  "fmt"
)

type User struct {
  name        string
  age         int
  bankBalance float32
  roleDetails RoleDetails
}

type RoleDetails struct {
  position string
  team     string
}

func main() {
  roleDetailForMohit := RoleDetails{
    position: "Software Engineer",
    team:     "Transport",
  }
  user := User{
    name:        "Mohit",
    age:         24,
    bankBalance: 100.0,
    roleDetails: roleDetailForMohit,
  }

  fmt.Println(user)
}

У цьому прикладі структура RoleDetails входить до складу структури User. Вивід буде:

{Mohit 24 100 {Software Engineer Transport}}

Для доступу до полів вкладеної структури використовуйте той самий оператор крапки:

user.roleDetails.position

Порівняння структур

Дві структури вважаються рівними, якщо всі їхні поля, як вбудовані, так і користувацькі, мають однакові значення. Однак, не всі типи даних піддаються порівнянню (наприклад, map неможливо порівняти безпосередньо). Розгляньмо приклад для наочності:

package main

import (
  "fmt"
)

type User struct {
  name        string
  age         int
  bankBalance float32
}

func main() {
  user1 := User{
    name:        "Mohit",
    age:         24,
    bankBalance: 100.0,
  }
  user2 := User{
    name:        "Mohit",
    age:         24,
    bankBalance: 100.0,
  }
  user3 := User{
    name:        "Nidhi",
    age:         21,
    bankBalance: 1000.0,
  }

  if user1 == user2 {
    fmt.Println("user1 і user2 рівні")
  } else {
    fmt.Println("user1 і user2 не рівні")
  }

  if user1 == user3 {
    fmt.Println("user1 і user3 рівні")
  } else {
    fmt.Println("user1 і user3 не рівні")
  }
}

Порожні та нульові структури також вважаються рівними. Порядок полів не має значення, для рівності важливо, щоб збігалися значення кожного поля. Результатом виконання цього коду буде:

user1 і user2 рівні
user1 і user3 не рівні

Висновок

Чудово!

Тепер ви готові застосовувати структури у своїх програмах на Golang. Ми вивчили основи, включаючи оголошення, ініціалізацію, доступ до полів та порівняння структур, а також розглянули вкладені структури. Ось кілька ресурсів для подальшого вивчення:

Звичайно, про структури можна дізнатися ще багато, але це чудовий старт. Сподіваюся, ця стаття була для вас корисною!

Продовжуйте досліджувати та навчатися!