Golang | Вопросы собесов
4.55K subscribers
29 photos
2 videos
812 links
Download Telegram
🤔 Что такое zero-value и какое оно у слайса ?

Концепция "нулевого значения" (zero-value) означает значение по умолчанию, которое получает переменная при ее объявлении, если она не была инициализирована явно. Нулевые значения зависят от типа данных переменной.

🟠int
0
🟠float64
0.0
🟠bool
false
🟠string
""
🟠указатели, интерфейсы, функции, каналы, карты, слайсы
nil

🚩Нулевое значение (zero-value) для слайса

Является nil. Это означает, что слайс, объявленный, но не инициализированный явно, указывает на nil и имеет длину и емкость равные нулю.
Нулевое значение для слайса
package main

import "fmt"

func main() {
var slice []int // Объявление слайса без инициализации
fmt.Println(slice) // []
fmt.Println(len(slice)) // 0
fmt.Println(cap(slice)) // 0
fmt.Println(slice == nil) // true
}


🚩Работа с нулевым значением

Можно работать так же, как и с обычным слайсом. Например, можно добавлять элементы с помощью функции append, и это будет работать корректно.
Использование append с nil-слайсом
package main

import "fmt"

func main() {
var slice []int // nil-слайс

// Добавление элемента в nil-слайс
slice = append(slice, 1)
fmt.Println(slice) // [1]
fmt.Println(len(slice)) // 1
fmt.Println(cap(slice)) // 1
fmt.Println(slice == nil) // false (теперь слайс больше не nil)
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21
🤔 Как думаешь, будут ли Map ordered?

Нет, в большинстве языков (например, Go) Map не гарантирует порядка хранения элементов.
1. Хранение данных зависит от хеширования ключей, что делает порядок непредсказуемым.
2. Если нужен упорядоченный Map, используйте структуру, где порядок задаётся вручную, например, с помощью slice.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
🤔 Как устроен слайс в Go ?

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

🚩Структура

🟠Указатель на базовый массив
Указатель на первый элемент массива, на который ссылается слайс.
🟠Длина (length)
Количество элементов, доступных в слайсе.
🟠Емкость (capacity)
Максимальное количество элементов, которое может содержать слайс без перераспределения памяти.

🚩Внутреннее устройство

Можно представить в виде структуры
type slice struct {
ptr *ElementType // Указатель на базовый массив
len int // Длина
cap int // Емкость
}


🟠Слайс из массива
Можно создать из массива, указав диапазон элементов:
package main

import "fmt"

func main() {
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // Слайс содержит элементы с индексами 1, 2, 3
fmt.Println(slice) // [2 3 4]
}


🟠Слайс с использованием функции make
Позволяет создать слайс определенной длины и емкости:
package main

import "fmt"

func main() {
slice := make([]int, 3, 5) // Слайс длиной 3 и емкостью 5
fmt.Println(slice) // [0 0 0]
}


🟠Доступ к элементам слайса
Осуществляется так же, как и к элементам массива:
package main

import "fmt"

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


🚩Основные операции с ними

🟠Добавление элементов
Для этого используется функция append
package main

import "fmt"

func main() {
slice := []int{1, 2, 3}
slice = append(slice, 4, 5) // Добавляем элементы 4 и 5 в конец слайса
fmt.Println(slice) // [1 2 3 4 5]
}


🟠Извлечение подмножества слайса (slicing)
Можно создавать новые слайсы на основе существующих
package main

import "fmt"

func main() {
slice := []int{1, 2, 3, 4, 5}
subSlice := slice[1:4] // Слайс содержит элементы с индексами 1, 2, 3
fmt.Println(subSlice) // [2 3 4]
}


🟠Копирование слайсов
Для этого используется функция copy
package main

import "fmt"

func main() {
src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)
fmt.Println(dst) // [1 2 3]
}


🚩Динамическое изменение длины и емкости

Могут автоматически изменять свою емкость при добавлении новых элементов с помощью append. Когда емкость текущего массива недостаточна для добавления новых элементов, создается новый массив с большей емкостью, в который копируются существующие элементы.
package main

import "fmt"

func main() {
slice := make([]int, 3, 5)
fmt.Println("Before append:", slice, "Len:", len(slice), "Cap:", cap(slice))

slice = append(slice, 1, 2, 3)
fmt.Println("After append:", slice, "Len:", len(slice), "Cap:", cap(slice))

slice = append(slice, 4)
fmt.Println("After another append:", slice, "Len:", len(slice), "Cap:", cap(slice))
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
🤔 Как правильно объявлять Map?

1. Инициализация: используйте make для создания карты, например, make(map[string]int).
2. Литералы: для статических данных можно использовать литералы, например, map[string]int{"key": 1}.
3. Всегда проверяйте существование элемента с помощью value, ok := map[key], чтобы избежать ошибок доступа к несуществующим ключам.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Как работает append в слайсе ?

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

🚩Как он работает

🟠Если емкости достаточно
Если текущий подлежащий массив слайса имеет достаточно места (емкости) для добавления новых элементов, append просто добавляет элементы к существующему массиву.
🟠Если емкости недостаточно
Если емкость текущего массива недостаточна для размещения новых элементов, append выделяет новый массив, копирует в него существующие элементы и добавляет новые элементы. Новый массив будет иметь увеличенную емкость (как правило, в два раза больше, чем предыдущая).

Синтаксис
slice = append(slice, elem1, elem2, ...)


Пример использования
package main

import "fmt"

func main() {
// Создаем слайс из 3 целых чисел
slice := []int{1, 2, 3}

// Добавляем один элемент
slice = append(slice, 4)

// Добавляем несколько элементов
slice = append(slice, 5, 6, 7)

// Выводим слайс
fmt.Println(slice) // Выводит: [1 2 3 4 5 6 7]
}


🚩Объяснение работы

1⃣Начальный слайс
Создаем слайс с тремя элементами [1, 2, 3].
slice := []int{1, 2, 3}   


2⃣Добавление одного элемента
Добавляем элемент 4 к слайсу. Теперь слайс содержит [1, 2, 3, 4].
slice = append(slice, 4)   


3⃣Добавление нескольких элементов
Добавляем элементы 5, 6, и 7. Теперь слайс содержит [1, 2, 3, 4, 5, 6, 7].
slice = append(slice, 5, 6, 7)   


4⃣Вывод слайса
Выводим слайс, который содержит [1, 2, 3, 4, 5, 6, 7].
fmt.Println(slice)   


Работа с емкостью и длиной
package main

import "fmt"

func main() {
slice := []int{1, 2, 3}
fmt.Printf("Before append: len=%d cap=%d %v\n", len(slice), cap(slice), slice)

slice = append(slice, 4)
fmt.Printf("After append: len=%d cap=%d %v\n", len(slice), cap(slice), slice)

slice = append(slice, 5, 6, 7)
fmt.Printf("After multiple appends: len=%d cap=%d %v\n", len(slice), cap(slice), slice)
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Как быстро можно что-то найти, если искать по индексу в слайсе и в Map?

В слайсе поиск по индексу имеет сложность O(1), так как элементы хранятся последовательно в памяти.
В Map поиск по ключу в среднем имеет сложность O(1) благодаря хешированию, но может ухудшиться до O(n) при большом количестве коллизий.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1😁1
🤔 Как устроен массив в Go?

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

🚩Основные характеристики

🟠Фиксированный размер
Размер массива задается при его объявлении и не может изменяться во время выполнения программы.
🟠Тип элементов
Все элементы массива имеют один и тот же тип.
🟠Непосредственное хранение данных
В отличие от слайсов, массивы хранят свои элементы в непрерывном блоке памяти.

🟠Объявление массива
С указанием типа элементов и фиксированного размера. Это объявление создает массив из пяти целых чисел, инициализированных нулями.
var arr [5]int


🟠Инициализация массива
Массивы могут быть инициализированы при объявлении
arr := [5]int{1, 2, 3, 4, 5}


Можно также инициализировать массив частично, оставив остальные элементы равными нулям:
arr := [5]int{1, 2}


🟠Доступ к элементам
Осуществляется с использованием индексов, начиная с 0
fmt.Println(arr[0]) // 1
arr[1] = 10
fmt.Println(arr[1]) // 10


🟠Длина массива
Фиксирована и задается при его объявлении. Ее можно получить с помощью функции len
fmt.Println(len(arr)) // 5


🟠Копирование массива
При присваивании одного массива другому копируются все элементы:
arr1 := [5]int{1, 2, 3, 4, 5}
arr2 := arr1
arr2[0] = 10
fmt.Println(arr1) // [1 2 3 4 5]
fmt.Println(arr2) // [10 2 3 4 5]


🟠Передача массива в функции
При этом копируется весь массив:
func modifyArray(a [5]int) {
a[0] = 10
}

arr := [5]int{1, 2, 3, 4, 5}
modifyArray(arr)
fmt.Println(arr) // [1 2 3 4 5]


🚩Сравнение

🟠Размер
Массивы имеют фиксированный размер, тогда как слайсы динамичны.

🟠Производительность
Массивы могут быть более производительными для небольших коллекций данных из-за отсутствия накладных расходов на управление динамическими данными.

🟠Гибкость: Слайсы более гибки благодаря динамическому изменению размера и доступным методам.

Использование массивов
package main

import (
"fmt"
)

func main() {
// Объявление и инициализация массива
arr := [5]int{1, 2, 3, 4, 5}

// Доступ к элементам
fmt.Println("First element:", arr[0]) // First element: 1

// Изменение элементов
arr[1] = 10
fmt.Println("Modified array:", arr) // Modified array: [1 10 3 4 5]

// Длина массива
fmt.Println("Length of array:", len(arr)) // Length of array: 5

// Копирование массива
arr2 := arr
arr2[0] = 20
fmt.Println("Original array:", arr) // Original array: [1 10 3 4 5]
fmt.Println("Copied array:", arr2) // Copied array: [20 10 3 4 5]

// Передача массива в функцию
modifyArray(arr)
fmt.Println("Array after modifyArray call:", arr) // Array after modifyArray call: [1 10 3 4 5]
}

func modifyArray(a [5]int) {
a[0] = 10
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Какие функции у Map?

1. Добавление элемента: map[key] = value.
2. Получение элемента: value, ok := map[key] — возвращает значение и флаг существования.
3. Удаление элемента: delete(map, key).
4. Итерация: for key, value := range map.
5. Проверка существования: с помощью ok из выражения value, ok := map[key].


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯2👀2👍1
🤔 Как работать со слайсами?

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

🚩Что это такое?

Это динамическая последовательность элементов одного типа, которая предоставляет доступ к части или всем элементам массива без копирования данных. Он содержит три компонента:
Указатель на массив.
Длина (количество элементов в слайсе).
Ёмкость (максимальное количество элементов, которые могут быть включены в слайс без перераспределения памяти).

🚩Почему они нужны?

Слайсы позволяют работать с массивами более гибко:
🟠Динамическая длина
В отличие от массивов, длина слайса может изменяться.
🟠Передача данных
Слайсы можно передавать в функции и возвращать из них, не копируя данные.
🟠Удобство работы
Предоставляют множество встроенных функций для работы с последовательностями данных.

🚩Создать слайс можно несколькими способами:

Из массива
    arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // слайс содержит элементы {2, 3, 4}


Используя make
slice := make([]int, 5)  // создаёт слайс длиной и ёмкостью 5, заполненный нулями    


Литерал слайса
slice := []int{1, 2, 3, 4, 5}    


🚩Основные операции

Доступ к элементам
fmt.Println(slice[0])  // выводит первый элемент слайса    


Изменение элементов
slice[1] = 10  // изменяет второй элемент слайса    


Добавление элементов
slice = append(slice, 6, 7)  // добавляет элементы 6 и 7 к слайсу    


Срезка (slicing)
newSlice := slice[1:3]  // создаёт новый слайс с элементами с 1-го по 3-й    


Рассмотрим пример функции, которая добавляет элемент в слайс и возвращает новый слайс
package main

import "fmt"

func main() {
nums := []int{1, 2, 3}
nums = append(nums, 4) // добавление элемента
fmt.Println(nums) // выводит [1, 2, 3, 4]
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Зачем `append` возвращает слайс?

append возвращает слайс, чтобы учесть возможное перераспределение памяти при добавлении элементов. Новый слайс может ссылаться на другой массив, если исходного размера недостаточно, поэтому важно использовать возвращаемое значение.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
🤔 Как Go МАПы сделать более потокобезопасными?

Карты (maps) не являются потокобезопасными. Это означает, что если несколько горутин пытаются одновременно читать и записывать данные в карту, могут возникнуть состояния гонки, приводящие к некорректным результатам или панике программы.

🚩Способы обеспечения потокобезопасности

🟠Использование sync.Mutex
Позволяют контролировать доступ к карте, обеспечивая, что только одна горутина имеет доступ к карте в любой момент времени.
package main

import (
"fmt"
"sync"
)

type SafeMap struct {
m map[string]int
mux sync.Mutex
}

func (sm *SafeMap) Set(key string, value int) {
sm.mux.Lock()
defer sm.mux.Unlock()
sm.m[key] = value
}

func (sm *SafeMap) Get(key string) (int, bool) {
sm.mux.Lock()
defer sm.mux.Unlock()
value, exists := sm.m[key]
return value, exists
}

func main() {
sm := SafeMap{m: make(map[string]int)}
sm.Set("Alice", 25)

value, exists := sm.Get("Alice")
if exists {
fmt.Println("Value:", value)
} else {
fmt.Println("Key not found")
}
}


🟠Использование sync.RWMutex
Позволяют одновременный доступ для чтения нескольким горутинам, блокируя доступ для записи. Это улучшает производительность при частых операциях чтения.
package main

import (
"fmt"
"sync"
)

type SafeMap struct {
m map[string]int
mux sync.RWMutex
}

func (sm *SafeMap) Set(key string, value int) {
sm.mux.Lock()
defer sm.mux.Unlock()
sm.m[key] = value
}

func (sm *SafeMap) Get(key string) (int, bool) {
sm.mux.RLock()
defer sm.mux.RUnlock()
value, exists := sm.m[key]
return value, exists
}

func main() {
sm := SafeMap{m: make(map[string]int)}
sm.Set("Alice", 25)

value, exists := sm.Get("Alice")
if exists {
fmt.Println("Value:", value)
} else {
fmt.Println("Key not found")
}
}


🟠Использование sync.Map
Предоставляет готовую реализацию потокобезопасной карты. Он полезен, когда нужна простая потокобезопасная карта без необходимости управлять блокировками вручную.
package main

import (
"fmt"
"sync"
)

func main() {
var sm sync.Map

// Запись значения
sm.Store("Alice", 25)

// Чтение значения
value, exists := sm.Load("Alice")
if exists {
fmt.Println("Value:", value)
} else {
fmt.Println("Key not found")
}

// Удаление значения
sm.Delete("Alice")
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Как устроен массив?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Назови преимущества горутин перед потоками ОС?

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

Легковесность
Горутины потребляют значительно меньше памяти и ресурсов по сравнению с потоками ОС. Каждая горутина стартует с размером стека порядка 2 КБ, тогда как поток ОС требует гораздо большего размера стека (обычно несколько мегабайт).

Планировщик Go
Горутины управляются встроенным планировщиком Go, а не планировщиком ОС. Планировщик Go распределяет выполнение горутин по доступным потокам ОС, используя концепцию "M:N" (много горутин на несколько потоков).

Отсутствие необходимости ручного управления
Создание, синхронизация и управление горутинами намного проще благодаря встроенным средствам Go, таким как каналы (channels) и sync-пакет. В то время как работа с потоками ОС требует дополнительных усилий для синхронизации (мьютексы, условные переменные и т.д.).

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

Простота и удобство
Синтаксис и использование горутин интуитивно понятны. Для запуска достаточно добавить go перед вызовом функции:

package main

import (
"fmt"
"time"
)

func sayHello() {
for i := 0; i < 5; i++ {
fmt.Println("Hello")
time.Sleep(100 * time.Millisecond)
}
}

func main() {
go sayHello() // Запускаем горутину
fmt.Println("World")
time.Sleep(1 * time.Second) // Даем горутине время завершиться
}


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

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥21
🤔 Как устроен слайс?

Это гибкая структура, представляющая ссылку на часть массива. Он включает указатель на массив, длину (len) и ёмкость (cap) — максимальное количество элементов, которое может быть добавлено без перераспределения памяти.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
🤔 Как ООП в Go реализовано?

Концепции объектно-ориентированного программирования (ООП) реализованы несколько иначе, чем в традиционных ООП-языках, таких как Java или C++. Не использует классы, наследование и полиморфизм на основе классов в привычном понимании. Вместо этого он применяет интерфейсы, структуры и встраивание для достижения гибкости и мощи ООП.

🟠Структуры вместо классов
Основной способ организации и капсуляции данных — это структуры (structs). Структуры объединяют данные в одну сущность, но в отличие от классов, они не включают определение методов внутри себя. Вместо этого методы определяются отдельно и ассоциируются со структурой через определение получателя метода.
type Person struct {
Name string
Age int
}

func (p Person) Greet() string {
return "Hello, my name is " + p.Name
}


🟠Интерфейсы для полиморфизма
Реализуется через интерфейсы. Интерфейс — это набор сигнатур методов. Тип считается реализующим интерфейс, если он имеет все методы, указанные в интерфейсе. Важной особенностью интерфейсов в Go является то, что типы могут удовлетворять интерфейсам неявно, без специального объявления.
type Greeter interface {
Greet() string
}

func GreetSomeone(g Greeter) {
fmt.Println(g.Greet())
}


🟠Встраивание для композиции
Один из способов реализации композиции — встраивание структур. Можно встроить одну структуру в другую, что позволяет делегировать часть работы встроенной структуре.
type Employee struct {
Person
Position string
}

func (e Employee) Work() string {
return e.Name + " is working as a " + e.Position
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
🤔 Как можно создать слайс?

1. С помощью литерала: s := []int{1, 2, 3}.
2. Через функцию make: s := make([]int, length, capacity).
3. Срезав массив: s := array[start:end].


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3
🤔 Как избежать deadlock?

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

🚩Чтобы избежать deadlock, нужно следовать этим принципам

🟠Грамотно проектировать порядок блокировок
Если несколько горутин используют блокировки (например, через мьютексы), убедитесь, что все они захватывают их в одном и том же порядке.
func main() {
var mu1, mu2 sync.Mutex

go func() {
mu1.Lock()
defer mu1.Unlock()

mu2.Lock()
defer mu2.Unlock()
}()

go func() {
mu2.Lock()
defer mu2.Unlock()

mu1.Lock()
defer mu1.Unlock()
}()
}


🟠Не блокировать каналы навсегда
Каналы должны всегда иметь возможность отправки и получения данных. Если одна сторона (отправитель или получатель) заблокирована навсегда, возникает deadlock.
func main() {
ch := make(chan int)
ch <- 42 // Deadlock, так как никто не читает из канала
}


🟠Закрывайте каналы правильно
Каналы нужно закрывать только со стороны отправителя, и только тогда, когда больше не будет отправок данных. Неправильное закрытие или отсутствие закрытия может привести к проблемам, включая deadlock.
ch := make(chan int)
close(ch) // Закрыт слишком рано
ch <- 42 // Паника


🟠Избегайте ситуаций с ожиданием себя
Иногда deadlock происходит, если горутина ждет сама себя.
func main() {
ch := make(chan int)
ch <- 1
fmt.Println(<-ch) // Никогда не выполнится
}


🟠Использовать тайм-ауты и селекторы
Go позволяет избегать блокировок с помощью механизма тайм-аутов и оператора select. Если операция занимает слишком много времени, можно выполнить альтернативное действие.
func main() {
ch := make(chan int)

select {
case data := <-ch:
fmt.Println("Получены данные:", data)
case <-time.After(1 * time.Second):
fmt.Println("Тайм-аут, завершение")
}
}


🟠Используйте инструменты анализа
Go предоставляет утилиту go run -race, которая помогает выявлять гонки данных и другие проблемы, связанные с синхронизацией.
go run -race main.go


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое zero-value и какое оно у слайса?

Это nil. Такой слайс имеет длину и ёмкость равные нулю и не ссылается на какой-либо массив.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👾2
🤔 Какое свойство должно быть у ключа в Map?

Ключи в map (карте) должны обладать определенными свойствами, чтобы быть допустимыми и корректно работать с хеш-таблицей. Важно понимать, что ключи должны поддерживать операцию сравнения и быть хешируемыми.

🚩Свойства ключей

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

🟠Хешируемость
Ключи должны быть хешируемыми. Это значит, что для ключей должна существовать функция, которая преобразует их в хеш-код. Хеш-код используется для определения позиции ключа в хеш-таблице.

🚩Допустимые типы ключей

Булевый тип (bool)
  m := map[bool]string{
true: "Yes",
false: "No",
}


Целочисленные типы (int, int8, int16, int32, int64, а также их беззнаковые эквиваленты uint, uint8, uint16, uint32, uint64)
  m := map[int]string{
1: "One",
2: "Two",
}


Числа с плавающей точкой (float32, float64)
  m := map[float64]string{
1.1: "One point one",
2.2: "Two point two",
}


Строки (string)
  m := map[string]int{
"Alice": 25,
"Bob": 30,
}


Составные типы (структуры, массивы), при условии, что все их поля также поддерживают сравнение с помощью оператора ==
  type Key struct {
FirstName string
LastName string
}

m := map[Key]int{
{"Alice", "Smith"}: 1,
{"Bob", "Johnson"}: 2,
}


🚩Недопустимые типы ключей

🟠Срезы (slice)
Срезы не поддерживают операцию сравнения с использованием оператора == (только сравнение с nil).
🟠Карты (map)
Карты не поддерживают операцию сравнения.
🟠Функции (func)
Функции не поддерживают операцию сравнения.

package main

import "fmt"

type Person struct {
FirstName string
LastName string
}

func main() {
// Создаем карту с ключами типа Person
m := make(map[Person]int)

// Вставляем значения в карту
m[Person{"Alice", "Smith"}] = 25
m[Person{"Bob", "Johnson"}] = 30

// Выводим значения из карты
fmt.Println(m[Person{"Alice", "Smith"}]) // Выводит: 25
fmt.Println(m[Person{"Bob", "Johnson"}]) // Выводит: 30
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3