Мы рассмотрим два составных типа данных Go: срезы и карты. Мы начнем с краткого объяснения того, что это за типы, а затем углубимся в практические примеры их использования. К концу вы научитесь создавать, манипулировать и использовать срезы и карты в Go.

Ломтики

1.1 Что такое слайсы?

Срезы в Go — это гибкий и мощный интерфейс для последовательностей типизированных данных. Они построены поверх массивов, обеспечивая динамический слой, который поддерживает автоматическое изменение размера.

package main

import "fmt"

func main() {
    nums := []int{1, 2, 3, 4, 5} // defining a slice
    fmt.Println(nums)
}

1.2 Создание и инициализация слайсов

Срезы можно создавать с помощью функции make, которая также позволяет указать емкость.

package main

import "fmt"

func main() {
    nums := make([]int, 3, 5) // slice of type int with length 3 and capacity 5
    fmt.Println(nums)
}

1.3 Работа со срезами

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

package main

import "fmt"

func main() {
    nums := []int{1, 2, 3}
    nums = append(nums, 4, 5) // append values to slice
    fmt.Println(nums)
}

1.4 Нарезка срезов

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

package main

import "fmt"

func main() {
    nums := []int{1, 2, 3, 4, 5}
    sub := nums[1:3] // slice of nums from index 1 (inclusive) to 3 (exclusive)
    fmt.Println(sub)
}

Карты

2.1 Что такое карты?

Карты в Go представляют собой неупорядоченный набор пар ключ-значение. Они похожи на словари в Python или объекты в JavaScript.

package main

import "fmt"

func main() {
    m := map[string]int{"Alice": 25, "Bob": 30} // defining a map
    fmt.Println(m)
}

2.2 Создание и инициализация карт

Вы можете создать карту, используя функцию make. Нулевое значение карты равно nil.

package main

import "fmt"

func main() {
    m := make(map[string]int) // map of string keys to int values
    fmt.Println(m)
}

2.3 Работа с картами

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

package main

import "fmt"

func main() {
    m := make(map[string]int)

    // Add new keys
    m["Alice"] = 25
    m["Bob"] = 30
    fmt.Println(m)

    // Update keys
    m["Alice"] = 26
    fmt.Println(m)

    // Access values
    age := m["Alice"]
    fmt.Println(age)

    // Check if a key is present
    _, ok := m["Charlie"]
    fmt.Println(ok) // prints: false
}

2.4 Удаление с Карт

Вы можете удалять записи с карты с помощью встроенной функции delete.

package main

import "fmt"

func main() {
    m := make(map[string]int)

    // Add new keys
    m["Alice"] = 25
    m["Bob"] = 30
    fmt.Println(m) // prints: map[Alice:25 Bob:30]

    // Delete a key
    delete(m, "Alice")
    fmt.Println(m) // prints: map[Bob:30]
}

2.5 Перебор карт

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

package main

import "fmt"

func main() {
    m := make(map[string]int)
    m["Alice"] = 25
    m["Bob"] = 30

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

Примеры из реального мира

3.1 Использование срезов в обработке данных

Предположим, мы хотим рассчитать средний балл класса. Мы можем использовать срез для хранения оценок и их обработки.

package main

import "fmt"

func average(scores []float64) float64 {
    total := 0.0
    for _, score := range scores {
        total += score
    }
    return total / float64(len(scores))
}

func main() {
    scores := []float64{90.5, 85.0, 78.0, 92.0, 88.5}
    avg := average(scores)
    fmt.Printf("The average score is %.2f\n", avg)
}

3.2 Использование карт для подсчета частот

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

package main

import (
    "fmt"
    "strings"
)

func wordCount(text string) map[string]int {
    words := strings.Fields(text) // split the text into words
    counts := make(map[string]int)
    for _, word := range words {
        counts[word]++
    }
    return counts
}

func main() {
    text := "go is easy to learn go is fun go is powerful"
    counts := wordCount(text)
    fmt.Println(counts)
}

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

Подробнее о фрагментах и ​​картах в Go

4.1 Работа с многомерными срезами

Как и массивы, срезы могут быть многомерными.

package main

import "fmt"

func main() {
    // 2D slice
    matrix := [][]int{
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},
    }

    fmt.Println(matrix)
}

4.2 Карты срезов

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

package main

import "fmt"

func main() {
    // map of string keys to slice of int values
    m := map[string][]int{
        "odd":  []int{1, 3, 5, 7, 9},
        "even": []int{2, 4, 6, 8},
    }

    fmt.Println(m)
}

4.3 Копирование фрагментов

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

package main

import "fmt"

func main() {
    nums := []int{1, 2, 3, 4, 5}
    copyNums := make([]int, len(nums))
    copy(copyNums, nums)
    copyNums[0] = 100
    fmt.Println(nums)      // prints: [1 2 3 4 5]
    fmt.Println(copyNums)  // prints: [100 2 3 4 5]
}

Функции среза и карты

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

package main

import "fmt"

// function that takes a slice and map as arguments
func updatePrices(prices []float64, adjustments map[string]float64) {
    for i, price := range prices {
        adjustment, ok := adjustments[fmt.Sprint(price)]
        if ok {
            prices[i] = price + adjustment
        }
    }
}

func main() {
    prices := []float64{10.0, 20.0, 30.0, 40.0}
    adjustments := map[string]float64{"10": 1.0, "30": 2.0}
    updatePrices(prices, adjustments)
    fmt.Println(prices)  // prints: [11 20 32 40]
}

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

Заключение

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

Спасибо за внимание!

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

Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 💰 Бесплатный курс собеседования по программированию ⇒ Просмотреть курс
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу