Сложные типы данных

3. Сложные типы данных #

3.1 Массивы и срезы #

Массивы #

Массив в Go имеет фиксированную длину, которая определяется при объявлении и является частью его типа.

Создание и инициализация: #

var arr [5]int       // Массив из 5 элементов типа int
arr[0] = 10          // Установка значения
fmt.Println(arr)     // [10 0 0 0 0]

arr2 := [3]int{1, 2, 3} // Инициализация
fmt.Println(arr2)       // [1 2 3]

arr3 := [...]int{4, 5, 6} // Размер определяется автоматически
fmt.Println(arr3)         // [4 5 6]

Итерация по массиву: #

for i, v := range arr {
    fmt.Printf("Index: %d, Value: %d\n", i, v)
}

Срезы #

Срезы — это гибкие и удобные для использования динамические массивы, которые строятся на основе массивов.

Создание и операции: #

slice := []int{1, 2, 3, 4} // Создание среза
fmt.Println(slice)         // [1 2 3 4]

slice = append(slice, 5)   // Добавление элемента
fmt.Println(slice)         // [1 2 3 4 5]

Операции среза: #

subSlice := slice[1:3] // Срез от индекса 1 до 3 (не включая 3)
fmt.Println(subSlice)  // [2 3]

slice[2] = 10          // Изменение значения в оригинальном срезе
fmt.Println(slice)     // [1 2 10 4 5]

Создание среза через make: #

newSlice := make([]int, 3, 5) // Длина 3, емкость 5
fmt.Println(newSlice)         // [0 0 0]

Копирование срезов: #

copySlice := make([]int, len(slice))
copy(copySlice, slice) // Копирование содержимого
fmt.Println(copySlice) // [1 2 10 4 5]

3.2 Карты (мапы) #

Создание карты: #

m := make(map[string]int) // Ключ — строка, значение — int
m["one"] = 1
m["two"] = 2
fmt.Println(m) // map[one:1 two:2]

Работа с элементами карты: #

value, exists := m["one"]
if exists {
    fmt.Println(value) // 1
} else {
    fmt.Println("Key does not exist")
}

Удаление ключа: #

delete(m, "one")
fmt.Println(m) // map[two:2]

Итерирование по карте: #

for key, value := range m {
    fmt.Printf("Key: %s, Value: %d\n", key, value)
}

3.3 Структуры и методы #

Определение структуры: #

type Person struct {
    Name string
    Age  int
}

person := Person{Name: "Alice", Age: 30}
fmt.Println(person) // {Alice 30}

Изменение полей структуры: #

person.Age = 31
fmt.Println(person.Age) // 31

Методы для структур: #

Методы позволяют добавлять функции, связанные с определенной структурой.

func (p Person) Greet() {
    fmt.Printf("Hello, my name is %s!\n", p.Name)
}

person.Greet() // Hello, my name is Alice!

Методы с изменением структуры: #

Чтобы изменить структуру внутри метода, используйте указатель:

func (p *Person) HaveBirthday() {
    p.Age++
}

person.HaveBirthday()
fmt.Println(person.Age) // 32

3.4 Встраивание структур #

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

Пример: #

type Address struct {
    City  string
    State string
}

type Person struct {
    Name    string
    Age     int
    Address // Встраивание структуры Address
}

person := Person{
    Name:    "Alice",
    Age:     30,
    Address: Address{City: "NYC", State: "NY"},
}
fmt.Println(person.City) // NYC

Встраивание предоставляет доступ к полям без необходимости указывать имя встраиваемой структуры.


3.5 Работа с nil и пустыми значениями #

nil в Go #

nil обозначает отсутствие значения и используется для ссылочных типов:

  • Срезы
  • Карты
  • Каналы
  • Интерфейсы
  • Указатели

Пример:

var p *int
if p == nil {
    fmt.Println("p is nil") // p is nil
}

Пустые значения #

Каждый тип имеет пустое значение по умолчанию:

  • int0
  • string""
  • boolfalse
  • Указатели, срезы, карты → nil

Пример:

var str string
fmt.Println(str) // ""

Проверка пустых значений: #

m := make(map[string]int)
if len(m) == 0 {
    fmt.Println("Map is empty")
}

Безопасная работа с nil: #

Попытка добавления элементов в nil-карту вызывает панику:

var m map[string]int // Карта равна nil
// m["key"] = 1       // Паника!
m = make(map[string]int)
m["key"] = 1
fmt.Println(m)

Советы по работе со сложными типами данных #

  1. Используйте срезы вместо массивов для гибкости.
  2. Для работы с большими данными предпочитайте карты.
  3. Структуры идеально подходят для создания сложных сущностей с множеством атрибутов.
  4. Проверяйте значения на nil, чтобы избежать ошибок во время выполнения.
  5. Практикуйте композицию с помощью встраивания структур вместо наследования.

Эти знания позволят эффективно работать со сложными данными в Go и строить производительные приложения!