Golang | Вопросы собесов
4.75K subscribers
31 photos
969 links
Download Telegram
Что такое функция copy ?
Спросят с вероятностью 8%

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

Синтаксис функции
func copy(dst, src []T) int


dst: слайс назначения (куда будут копироваться элементы).
src: слайс источника (откуда будут копироваться элементы).

Примеры использования copy

Пример 1: Копирование слайса

package main

import "fmt"

func main() {
src := []int{1, 2, 3, 4, 5}
dst := make([]int, 5) // Создаем слайс назначения длиной 5

n := copy(dst, src) // Копируем элементы из src в dst
fmt.Println("Copied elements:", n) // 5
fmt.Println("Destination slice:", dst) // [1 2 3 4 5]
}


Пример 2: Частичное копирование

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

import "fmt"

func main() {
src := []int{1, 2, 3, 4, 5}
dst := make([]int, 3) // Создаем слайс назначения длиной 3

n := copy(dst, src) // Копируем элементы из src в dst
fmt.Println("Copied elements:", n) // 3
fmt.Println("Destination slice:", dst) // [1 2 3]
}


Пример 3: Копирование в пустой слайс

Если длина слайса источника меньше длины слайса назначения, то копируются только те элементы, которые имеются в источнике.
package main

import "fmt"

func main() {
src := []int{1, 2, 3}
dst := make([]int, 5) // Создаем слайс назначения длиной 5

n := copy(dst, src) // Копируем элементы из src в dst
fmt.Println("Copied elements:", n) // 3
fmt.Println("Destination slice:", dst) // [1 2 3 0 0]
}


Применение функции copy

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

Изменение части слайса.
Создание независимой копии слайса, чтобы изменения в копии не затрагивали исходный слайс.
Реализация алгоритмов, требующих манипуляций с массивами данных.

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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍2
Как в Go пишут unit тесты со стандартным пакетом testing ?
Спросят с вероятностью 8%

Модульные тесты (unit tests) пишутся с использованием стандартного пакета testing. Они направлены на проверку отдельных функций или методов в изоляции, чтобы убедиться, что каждая функция работает корректно.

Как это делается:

1️⃣Создание тестового файла: Тестовые файлы должны иметь суффикс _test.go. Например, если у вас есть файл math.go, тестовый файл для него будет называться math_test.go.
2️⃣Написание тестовых функций: Тестовые функции должны начинаться с Test, а их имя должно быть описательным. Например, TestAdd для функции Add.
3️⃣Использование метода `t.Errorf` или t.Fatalf: Эти методы позволяют сообщать о провале теста. t.Errorf продолжает выполнение тестов после ошибки, а t.Fatalf завершает выполнение текущего теста.

Допустим, у нас есть простая функция для сложения двух чисел в файле math.go:
// file: math.go
package math

func Add(a, b int) int {
return a + b
}


Создадим тест для этой функции в файле math_test.go:
// file: math_test.go
package math

import "testing"

func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
t.Errorf("Add(2, 3) = %d; expected %d", result, expected)
}
}


Детали:

1️⃣Импорт пакетамер, TestAd Это обязательный шаг для использования функций и типов, предоставляемых пакетом testing.
2️⃣Определение тестовой функции: Функция должна принимать один аргумент типа *testing.T. Это структура, предоставляемая пакетом testing, которая используется для логирования и отчета об ошибках.
3️⃣Проверка результата: Внутри тестовой функции вы вызываете тестируемую функцию, проверяете результат и используете методы t.Errorf или t.Fatalf для сообщения о несоответствиях.

Расширенные возможности:

Табличные тесты: Полезны для тестирования нескольких сценариев с разными входными данными и ожидаемыми результатами.
func TestAddTableDriven(t *testing.T) {
tests := []struct {
a, b int
result int
}{
{1, 1, 2},
{2, 3, 5},
{10, -2, 8},
{-1, -1, -2},
}

for _, tt := range tests {
t.Run(fmt.Sprintf("%d+%d", tt.a, tt.b), func(t *testing.T) {
res := Add(tt.a, tt.b)
if res != tt.result {
t.Errorf("Add(%d, %d) = %d; expected %d", tt.a, tt.b, res, tt.result)
}
})
}
}


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


Эта команда автоматически находит все файлы с суффиксом _test.go, компилирует их и запускает тестовые функции.

Модульные тесты пишутся с использованием стандартного пакета testing. Они помогают убедиться, что отдельные функции работают правильно. Тесты создаются в файлах с суффиксом _test.go и включают тестовые функции, начинающиеся с Test, которые проверяют результаты работы функций и сообщают о несоответствиях.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍1
Что такое моки (mocks) ?
Спросят с вероятностью 8%

Моки (mocks) – это имитации объектов или компонентов, которые используются в тестировании для замены реальных объектов. Они помогают изолировать тестируемый код, эмулируя поведение зависимостей, таких как базы данных, внешние API или другие сервисы. Это особенно полезно в модульных тестах, где важно проверить функциональность конкретного блока кода без влияния внешних факторов.

Зачем они нужны:

1️⃣Изоляция тестируемого кода: Позволяют тестировать функциональность в изоляции, не затрагивая реальные зависимости.
2️⃣Ускорение тестирования: Исключение реальных зависимостей (например, обращения к базе данных или сетевых вызовов) делает тесты быстрее.
3️⃣Предсказуемость: Обеспечивают контроль над входными данными и поведением зависимостей, что позволяет точно проверять ожидаемое поведение.
4️⃣Удобство тестирования пограничных случаев: Позволяют легко имитировать ошибки и нестандартные ситуации, что бывает сложно с реальными объектами.

Как их использовать:

Для создания их часто используются интерфейсы и специальные библиотеки, такие как gomock или testify/mock.

Пример использования с testify/mock:

1️⃣Определение интерфейса:
// file: user.go
package user

type User struct {
ID int
Name string
}

type UserRepository interface {
GetUserByID(id int) (*User, error)
}


2️⃣Создание функции, использующей интерфейс:
// file: service.go
package user

type UserService struct {
Repo UserRepository
}

func (s *UserService) GetUserName(id int) (string, error) {
user, err := s.Repo.GetUserByID(id)
if err != nil {
return "", err
}
return user.Name, nil
}


3️⃣Написание теста с использованием мока:
// file: service_test.go
package user

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

// MockUserRepository is a mock implementation of the UserRepository interface.
type MockUserRepository struct {
mock.Mock
}

func (m *MockUserRepository) GetUserByID(id int) (*User, error) {
args := m.Called(id)
return args.Get(0).(*User), args.Error(1)
}

func TestGetUserName(t *testing.T) {
mockRepo := new(MockUserRepository)
service := UserService{Repo: mockRepo}

// Определяем поведение мока
mockRepo.On("GetUserByID", 1).Return(&User{ID: 1, Name: "Alice"}, nil)

// Выполнение теста
name, err := service.GetUserName(1)

// Проверка результатов
assert.NoError(t, err)
assert.Equal(t, "Alice", name)

// Проверка, что мок был вызван с правильными параметрами
mockRepo.AssertExpectations(t)
}


Объяснение:

1️⃣Определение интерфейса: Интерфейс UserRepository определяет метод GetUserByID.
2️⃣Использование интерфейса в сервисе: Сервис UserService использует UserRepository для получения информации о пользователе.
3️⃣Создание мока: Мы создаем мок MockUserRepository, реализующий интерфейс UserRepository.
4️⃣Определение поведения мока: Устанавливаем ожидания, что метод GetUserByID будет вызван с определенными параметрами и вернет заданные результаты.
5️⃣Тестирование сервиса: Проверяем, что метод GetUserName возвращает правильное значение, и что мок был вызван с ожидаемыми параметрами.

Моки – это заменители реальных объектов, используемые в тестировании для изоляции кода, ускорения тестов и создания предсказуемых условий. Для этого часто используют интерфейсы и библиотеки, такие как testify/mock.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🔥1
Как можно добавить элементы в слайс ?
Спросят с вероятностью 8%

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

Использование append для добавления элементов в слайс

1️⃣Добавление одного элемента

Чтобы это сделать используйте append следующим образом:
package main

import "fmt"

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


2️⃣Добавление нескольких элементов

Чтобы это сделать передайте их через запятую:
package main

import "fmt"

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


3️⃣Добавление элементов из другого слайса

Чтобы это сделать используйте оператор разворачивания (...):

package main

import "fmt"

func main() {
slice1 := []int{1, 2, 3}
slice2 := []int{4, 5, 6}
slice1 = append(slice1, slice2...) // Добавление элементов из slice2 в slice1
fmt.Println(slice1) // [1 2 3 4 5 6]
}


Пример динамического увеличения емкости слайса

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

import "fmt"

func main() {
slice := make([]int, 0, 2) // Создаем слайс длиной 0 и емкостью 2
fmt.Println("Initial:", slice, "Len:", len(slice), "Cap:", cap(slice))

// Добавляем элементы
slice = append(slice, 1)
fmt.Println("After append 1:", slice, "Len:", len(slice), "Cap:", cap(slice))

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

slice = append(slice, 3) // Емкость увеличивается автоматически
fmt.Println("After append 3:", slice, "Len:", len(slice), "Cap:", cap(slice))

slice = append(slice, 4, 5, 6) // Добавляем несколько элементов
fmt.Println("After append 4, 5, 6:", slice, "Len:", len(slice), "Cap:", cap(slice))
}


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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
1
🤔 Какое ключевое слово используется для создания нового типа в Go?
Anonymous Quiz
2%
define
15%
struct
74%
type
9%
new
Опишите алгоритм, как будет происходить вставка в Map ?
Спросят с вероятностью 8%

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

1️⃣Хеширование ключа: Вычисляется хеш-код для ключа с использованием функции хеширования. Это дает нам число, которое будет использоваться для определения позиции ключа в хеш-таблице.

2️⃣Определение индекса: Индекс в массиве корзин (buckets) вычисляется на основе хеш-кода и размера массива. Обычно используется операция побитового И (&) для получения индекса.

3️⃣Поиск корзины: С использованием вычисленного индекса определяется конкретная корзина, в которую будет помещен ключ.

4️⃣Проверка на коллизию: Если корзина уже содержит элементы, проверяется, есть ли в ней элемент с таким же ключом:
Если элемент с таким ключом уже существует, его значение обновляется новым значением.
Если элемент с таким ключом не найден, новый ключ-значение добавляется в корзину.

5️⃣Вставка элемента: Новый элемент добавляется в соответствующую корзину.

Алгоритм вставки на более низком уровне:

1️⃣Хеширование ключа:
        hash := hashFunction(key)


2️⃣Определение индекса:
        index := hash & (len(buckets) - 1)


3️⃣Поиск корзины и проверка на коллизию:
Проверяем корзину по индексу:
            bucket := buckets[index]

Итерируемся по элементам в корзине для поиска совпадения ключа:
            for _, element := range bucket {
if element.key == key {
element.value = newValue
return
}
}


4️⃣Добавление нового элемента:
Если совпадения ключа не найдено, добавляем новый элемент в корзину:
            bucket = append(bucket, newElement)


Пример вставки элемента в карту:
package main

import "fmt"

func main() {
// Создаем карту
myMap := make(map[string]int)

// Вставка элементов
myMap["Alice"] = 25
myMap["Bob"] = 30

// Обновление значения существующего ключа
myMap["Alice"] = 26

// Печать карты
fmt.Println(myMap)
}


В этом примере:
1️⃣Создается карта myMap с ключами типа string и значениями типа int.
2️⃣Вставляются пары ключ-значение: "Alice": 25 и "Bob": 30.
3️⃣Значение для ключа "Alice" обновляется на 26.
4️⃣Карта выводится на экран.

Важные моменты:

Коллизии: Если два ключа имеют один и тот же хеш-код, они попадают в одну корзину. Решение коллизий обычно осуществляется с помощью связных списков или других структур данных внутри каждой корзины.
Распределение хеша: Хорошая функция хеширования равномерно распределяет ключи по корзинам, минимизируя количество коллизий.
Динамическое изменение размера: При переполнении корзин карта автоматически увеличивает размер массива корзин, чтобы поддерживать эффективное время выполнения операций.

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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍31🤯1
🤔 Какой из методов используется для добавления нового элемента в карту (map) в Go?
Anonymous Quiz
32%
append()
3%
insert()
8%
add()
56%
Присваивание по ключу
Как проверить слайс на пустоту ?
Спросят с вероятностью 8%

Существует несколько способов проверки слайса на пустоту. Выбор метода зависит от конкретной ситуации и того, что именно вы подразумеваете под "пустотой". Рассмотрим различные подходы.

1️⃣Проверка длины слайса

Самый распространенный способ проверить, пустой ли слайс, — это проверить его длину с помощью функции len. Если длина слайса равна нулю, то слайс пустой.
package main

import "fmt"

func main() {
var slice1 []int // nil слайс
slice2 := []int{} // Пустой слайс, но не nil
slice3 := []int{1, 2, 3} // Непустой слайс

fmt.Println("slice1 is empty:", len(slice1) == 0) // true
fmt.Println("slice2 is empty:", len(slice2) == 0) // true
fmt.Println("slice3 is empty:", len(slice3) == 0) // false
}


2️⃣Проверка на nil

Иногда важно отличать nil слайс от пустого слайса с нулевой длиной. Для этого можно использовать сравнение с ним же.
package main

import "fmt"

func main() {
var slice1 []int // nil слайс
slice2 := []int{} // Пустой слайс, но не nil

fmt.Println("slice1 is nil:", slice1 == nil) // true
fmt.Println("slice2 is nil:", slice2 == nil) // false
}


Комбинированная проверка

В некоторых случаях может потребоваться отличать nil слайс от пустого слайса и одновременно проверять, пустой ли он. Это можно сделать с помощью комбинации проверок len и сравнения с nil.
package main

import "fmt"

func isEmpty(slice []int) bool {
return slice == nil || len(slice) == 0
}

func main() {
var slice1 []int // nil слайс
slice2 := []int{} // Пустой слайс, но не nil
slice3 := []int{1, 2, 3} // Непустой слайс

fmt.Println("slice1 is empty:", isEmpty(slice1)) // true
fmt.Println("slice2 is empty:", isEmpty(slice2)) // true
fmt.Println("slice3 is empty:", isEmpty(slice3)) // false
}


Для проверки слайса на пустоту обычно используют len(slice) == 0. Для проверки, является ли слайс nil, используют slice == nil. Для комбинированной проверки можно использовать оба условия.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍21
Что такое хэш-коллизия ?
Спросят с вероятностью 8%

Хэш-коллизия происходит, когда два различных ключа в хэш-таблице имеют одинаковое значение хэш-функции, что приводит к попытке размещения их в одной и той же корзине (bucket).

Почему они возникают:

1️⃣Ограниченное количество хэш-значений: Обычно возвращают значения в ограниченном диапазоне (например, 32-битное или 64-битное число), тогда как количество возможных ключей может быть значительно больше.
2️⃣Имперфектное хэширование: Даже хорошая хэш-функция не может идеально распределить все возможные ключи по всем возможным хэш-значениям, особенно при увеличении количества ключей.

Методы разрешения:

1️⃣Открытая адресация:
Линейное пробирование: При коллизии алгоритм проверяет следующую ячейку в массиве до тех пор, пока не найдет пустую ячейку.
          index = (hash + i) % len(buckets)

Квадратичное пробирование: Вместо линейного шага проверяются ячейки с квадратичным шагом.
          index = (hash + i*i) % len(buckets)

Двойное хеширование: Используются две разные хэш-функции для расчета шага пробирования.
          index = (hash1 + i*hash2) % len(buckets)


2️⃣Цепочки (Chaining):
Каждая корзина (bucket) является связным списком или другой структурой данных, в которой хранятся все элементы с одинаковым хэш-значением.
          type Node struct {
key string
value int
next *Node
}


Пример реализации цепочек:
package main

import (
"container/list"
"fmt"
)

// Простая хэш-таблица с цепочками
type HashTable struct {
buckets []*list.List
size int
}

// Создаем новую хэш-таблицу
func NewHashTable(size int) *HashTable {
buckets := make([]*list.List, size)
for i := range buckets {
buckets[i] = list.New()
}
return &HashTable{
buckets: buckets,
size: size,
}
}

// Хэш-функция
func (ht *HashTable) hash(key string) int {
hash := 0
for i := 0; i < len(key); i++ {
hash = (31 * hash) + int(key[i])
}
return hash % ht.size
}

// Вставка в хэш-таблицу
func (ht *HashTable) Insert(key string, value int) {
index := ht.hash(key)
bucket := ht.buckets[index]
for e := bucket.Front(); e != nil; e = e.Next() {
pair := e.Value.(map[string]int)
if _, ok := pair[key]; ok {
pair[key] = value
return
}
}
bucket.PushBack(map[string]int{key: value})
}

// Поиск в хэш-таблице
func (ht *HashTable) Search(key string) (int, bool) {
index := ht.hash(key)
bucket := ht.buckets[index]
for e := bucket.Front(); e != nil; e = e.Next() {
pair := e.Value.(map[string]int)
if val, ok := pair[key]; ok {
return val, true
}
}
return 0, false
}

func main() {
ht := NewHashTable(10)
ht.Insert("Alice", 25)
ht.Insert("Bob", 30)
ht.Insert("Charlie", 35)

if value, found := ht.Search("Alice"); found {
fmt.Println("Alice:", value)
} else {
fmt.Println("Alice not found")
}

if value, found := ht.Search("Bob"); found {
fmt.Println("Bob:", value)
} else {
fmt.Println("Bob not found")
}

if value, found := ht.Search("Eve"); found {
fmt.Println("Eve:", value)
} else {
fmt.Println("Eve not found")
}
}


Объяснение кода:
HashTable: Структура, представляющая хэш-таблицу с цепочками.
NewHashTable: Функция, создающая новую хэш-таблицу заданного размера.
hash: Простая хэш-функция для строк.
Insert: Метод для вставки ключ-значение в хэш-таблицу.
Search: Метод для поиска значения по ключу в хэш-таблице.

Хэш-коллизия возникает, когда два разных ключа имеют одинаковое хэш-значение. Основные методы разрешения коллизий включают открытую адресацию и цепочки. Можно использовать структуры данных, такие как списки, для реализации цепочек.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍1
Можно ли добавлять элементы в nil слайс ?
Спросят с вероятностью 8%

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

Пример:
package main

import "fmt"

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

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

// Добавление нескольких элементов
nilSlice = append(nilSlice, 2, 3, 4)
fmt.Println(nilSlice) // [1 2 3 4]
fmt.Println(len(nilSlice)) // 4
fmt.Println(cap(nilSlice)) // в зависимости от реализации, емкость может быть увеличена
}


Как он работает с nil слайсом

Когда вызывается append для nil слайса, происходит следующее:

1️⃣Проверка емкости: Go проверяет, достаточно ли емкости для добавления новых элементов.
2️⃣Выделение памяти: Если емкости недостаточно (что всегда будет в случае nil слайса), Go выделяет новый массив с достаточной емкостью для хранения существующих и новых элементов.
3️⃣Копирование элементов: Существующие элементы (если таковые имеются) копируются в новый массив.
4️⃣Добавление новых элементов: Новые элементы добавляются в массив.
5️⃣Возврат нового слайса: Возвращается новый слайс, который указывает на новый массив.
package main

import "fmt"

func main() {
var nilSlice []int

// Проверка начальных значений
fmt.Println("Initial nilSlice:", nilSlice) // []
fmt.Println("Length:", len(nilSlice)) // 0
fmt.Println("Capacity:", cap(nilSlice)) // 0
fmt.Println("Is nilSlice nil?", nilSlice == nil) // true

// Добавление первого элемента
nilSlice = append(nilSlice, 1)
fmt.Println("After append 1:", nilSlice) // [1]
fmt.Println("Length:", len(nilSlice)) // 1
fmt.Println("Capacity:", cap(nilSlice)) // 1
fmt.Println("Is nilSlice nil?", nilSlice == nil) // false

// Добавление нескольких элементов
nilSlice = append(nilSlice, 2, 3, 4)
fmt.Println("After append 2, 3, 4:", nilSlice) // [1 2 3 4]
fmt.Println("Length:", len(nilSlice)) // 4
fmt.Println("Capacity:", cap(nilSlice)) // >= 4
}


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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍1
🤔 Какое ключевое слово используется для объявления константы в Go?
Anonymous Quiz
96%
const
2%
constant
2%
final
0%
immutable
Что можно хранить в качестве ключа, если Float не использовать ?
Спросят с вероятностью 8%

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

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


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


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


4️⃣Указатели (любого типа):
        a, b := 1, 2
m := map[*int]string{
&a: "Pointer to a",
&b: "Pointer to b",
}


5️⃣Интерфейсы (при условии, что конкретные типы, которые они содержат, поддерживают сравнение):
        var i interface{} = "string"
m := map[interface{}]string{
i: "interface as key",
}


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

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


Почему float не рекомендуется использовать в качестве ключа

Проблемы с точностью: Плавающие числа (float) часто имеют проблемы с точностью представления. Два значения, которые математически равны, могут иметь небольшие различия в их бинарном представлении из-за ограничений точности. Это может привести к неожиданному поведению при сравнении ключей.
Стандарты IEEE 754: Плавающие числа следуют стандарту IEEE 754, который предусматривает такие значения, как NaN (Not a Number). В Go, NaN не равен сам себе (NaN != NaN), что делает их проблематичными для использования в качестве ключей в хэш-таблицах.

Рассмотрим пример использования структуры в качестве ключа в хэш-таблице:
package main

import "fmt"

type Person struct {
FirstName string
LastName string
}

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

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

// Поиск и вывод значений
fmt.Println("Alice Smith age:", m[Person{"Alice", "Smith"}])
fmt.Println("Bob Johnson age:", m[Person{"Bob", "Johnson"}])
}


В этом примере:
1️⃣Определение структуры: Создаем структуру Person с полями FirstName и LastName.
2️⃣Создание карты: Создаем карту m с ключами типа Person.
3️⃣Вставка значений: Вставляем в карту два значения с ключами типа Person.
4️⃣Поиск и вывод значений: Ищем значения по ключам и выводим их на экран.

В качестве ключей в хэш-таблицах можно использовать типы, которые поддерживают операцию сравнения с помощью оператора ==. Это включает булевые, целочисленные типы, строки, указатели, интерфейсы и составные типы, такие как структуры. Плавающие числа не рекомендуются из-за проблем с точностью и особенностей стандарта IEEE 754.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍1
🤔 Какой пакет используется для работы с временем в Go?
Anonymous Quiz
91%
"time"
7%
"datetime"
1%
"clock"
1%
"calendar"
Что такое nil слайс и чем отличается ?
Спросят с вероятностью 8%

Слайсы могут быть либо nil, либо ненулевыми. Понимание разницы между ними важно для правильного использования и управления памятью. Разберем, что такое nil слайс, как он отличается от ненулевого слайса, и какие особенности и применения есть у обоих.

nil

Это слайс, который не указывает ни на какой массив. Он имеет следующие характеристики:

1️⃣Указатель на базовый массив равен `nil`.
2️⃣Длина равна 0.
3️⃣Емкость равна 0.
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
}


Ненулевой (пустой)

Это слайс, который инициализирован и указывает на некоторый массив, даже если этот массив имеет нулевую длину. Такой слайс имеет ненулевую емкость.
package main

import "fmt"

func main() {
slice := make([]int, 0) // Создание пустого слайса с длиной 0
fmt.Println(slice) // []
fmt.Println(len(slice)) // 0
fmt.Println(cap(slice)) // В зависимости от реализации, например, 0 или больше
fmt.Println(slice == nil) // false
}


Отличия nil от ненулевого

1️⃣Инициализация:
nil слайс: Не инициализирован явно, инициализирован с nil.
Ненулевой слайс: Инициализирован явно, даже если длина равна 0.

2️⃣
Сравнение с
ain() {

nil слайс: slice == nil возвращает true.
Ненулевой слайс: slice == nil возвращает false.

3️⃣Использование в функциях:
Оба типа слайсов могут передаваться в функции и использоваться для операций, таких как добавление элементов с помощью append.
package main

import "fmt"

func main() {
var nilSlice []int
nonNilSlice := make([]int, 0)

nilSlice = append(nilSlice, 1)
nonNilSlice = append(nonNilSlice, 1)

fmt.Println(nilSlice) // [1]
fmt.Println(nonNilSlice) // [1]
fmt.Println(nilSlice == nil) // false
fmt.Println(nonNilSlice == nil) // false
}


Особенности и применения

Проверка на
  fmt.P

Иногда полезно проверять, является ли слайс nil, чтобы избежать ненужных операций или для специальной обработки.
        if slice == nil {
fmt.Println("Slice is nil")
} else {
fmt.Println("Slice is not nil")
}


Инициализация :
При этом, они будут заполняться позже, часто используют nil слайсы.
Для их создания фиксированной или предварительно известной емкости используют make.

nil — это слайс, который не указывает на массив и имеет длину и емкость 0. Ненулевой может иметь длину 0, но указывает на массив и обычно имеет емкость, отличную от 0. Понимание разницы между ними важно для правильного использования слайсов и управления памятью.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Какой ключевое слово используется для выхода из горутины в Go?
Anonymous Quiz
10%
exit
4%
stop
37%
return
49%
нет специального ключевого слова