Golang | Вопросы собесов
4.34K subscribers
28 photos
1 video
706 links
Download Telegram
🤔 В чем разница между императивным и декларативным?

Императивный подход описывает, как именно выполнить задачу, задавая пошаговые инструкции. Декларативный подход описывает, что нужно сделать, оставляя детали выполнения системе. Например, в программировании SQL декларативен, а C более императивен

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔Чем отличается RW Мьютекс от обычного?

RWMutex (Read-Write Mutex) позволяет разделять доступ для чтения и блокировать только для записи, в отличие от обычного Mutex, который блокирует как чтение, так и запись. С помощью RWMutex можно использовать RLock для параллельного доступа к данным в режиме чтения, что увеличивает производительность, если много горутин читают данные и редко их изменяют. Для записи используется Lock, который блокирует доступ к данным для всех других операций чтения и записи.

🚩Обычный мьютекс (sync.Mutex)

sync.Mutex используется для обеспечения эксклюзивного доступа к ресурсу для всех операций (чтение и запись). Подходит для сценариев с частыми операциями записи или равномерным распределением чтений и записей.
var mu sync.Mutex
var counter int

func increment() {
mu.Lock()
counter++
mu.Unlock()
}

func main() {
var wg sync.WaitGroup

for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
increment()
}()
}

wg.Wait()
fmt.Println("Counter:", counter)
}


🚩RW мьютекс (sync.RWMutex)

sync.RWMutex предоставляет два типа блокировок: для чтения (RLock) и для записи (Lock). Позволяет нескольким горутинам одновременно читать данные, если нет активных блокировок для записи. Улучшает производительность в сценариях с частыми чтениями и редкими записями.
var rwMu sync.RWMutex
var counter int

func readCounter() int {
rwMu.RLock()
defer rwMu.RUnlock()
return counter
}

func increment() {
rwMu.Lock()
counter++
rwMu.Unlock()
}

func main() {
var wg sync.WaitGroup

for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println("Read Counter:", readCounter())
}()
}

for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
increment()
}()
}

wg.Wait()
fmt.Println("Final Counter:", counter)
}


🚩Сравнение

🟠Эксклюзивность
sync.Mutex блокирует доступ для всех операций.
sync.RWMutex позволяет одновременное чтение, но блокирует доступ при записи.

🟠Производительность
sync.Mutex подходит для частых записей или равномерного распределения операций.
sync.RWMutex подходит для частых чтений и редких записей.

🟠Применение:
Используйте sync.Mutex для эксклюзивного доступа без различий между чтением и записью.
Используйте sync.RWMutex для улучшения производительности при частых чтениях.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое эвакуация, и в каком случае она будет происходить?

Эвакуация — это процесс перемещения объектов в новую область памяти, например из младшего поколения в старшее при сборке мусора. Она происходит, если объект переживает несколько циклов сборки мусора. Этот механизм помогает оптимизировать использование памяти.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Расскажи, что такое starvation/голодание?

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

🚩Основные причины голодания

🟠Приоритеты
Если потоки с более низким приоритетом постоянно вытесняются потоками с более высоким приоритетом, они могут вообще не получить доступ к ресурсу.
🟠Блокировки
При использовании мьютексов или других механизмов синхронизации, если один поток постоянно захватывает мьютекс, другие потоки могут не получить возможности захватить его и выполнить свою работу.
🟠Бесконечное ожидание
Потоки могут попасть в состояние бесконечного ожидания, если они не могут получить доступ к ресурсу из-за постоянной занятости другими потоками.

🚩Пример голодания

Один поток постоянно захватывает мьютекс, не давая другим потокам шанса выполнить свою работу. В этом примере функция greedyWorker постоянно захватывает мьютекс, блокируя доступ к sharedResource для других горутин (функций starvedWorker). Это приводит к тому, что starvedWorker не получает шанса выполнить свою работу.
package main

import (
"fmt"
"sync"
"time"
)

var mu sync.Mutex
var sharedResource int

func greedyWorker() {
for {
mu.Lock()
sharedResource++
fmt.Println("Greedy worker incremented sharedResource to:", sharedResource)
mu.Unlock()
time.Sleep(100 * time.Millisecond) // Короткая задержка для демонстрации
}
}

func starvedWorker(id int, wg *sync.WaitGroup) {
defer wg.Done()
mu.Lock()
fmt.Printf("Starved worker %d is running\n", id)
sharedResource++
mu.Unlock()
}

func main() {
var wg sync.WaitGroup
wg.Add(5)

go greedyWorker()

for i := 1; i <= 5; i++ {
go starvedWorker(i, &wg)
}

wg.Wait()
fmt.Println("Final sharedResource value:", sharedResource)
}


🚩Способы предотвращения голодания

🟠Справедливые блокировки
Используйте справедливые алгоритмы блокировки, которые предоставляют доступ к ресурсу в порядке очереди.
🟠Управление приоритетами
Обеспечьте сбалансированное управление приоритетами потоков, чтобы потоки с низким приоритетом также получали доступ к ресурсам.
🟠Использование других механизмов синхронизации
Например, вместо использования мьютексов, можно использовать каналы в Go для координации работы между горутинами.
🟠Разделение времени доступа:
Ограничьте время, в течение которого поток может удерживать мьютекс, чтобы другие потоки также могли получить доступ.

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

При добавлении элемента слайс увеличивается в два раза, если он достигает текущей ёмкости. Это позволяет минимизировать количество перераспределений памяти. Однако если ёмкости достаточно, увеличение не происходит.

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

Для обеспечения потокобезопасности мапы в Go обычно используется комбинация мьютексов (sync.Mutex) или RW-мьютексов (sync.RWMutex). Давайте рассмотрим, как каждый из них применяется для защиты мапы.

🚩Использование `sync.Mutex`

sync.Mutex обеспечивает эксклюзивный доступ к мапе для всех операций (чтение и запись). Это простой и эффективный способ синхронизации, но при частых операциях чтения может возникнуть узкое место, так как блокируются все операции.
package main

import (
"fmt"
"sync"
)

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

func NewSafeMap() *SafeMap {
return &SafeMap{
m: make(map[string]int),
}
}

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

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

func (sm *SafeMap) Delete(key string) {
sm.mu.Lock()
defer sm.mu.Unlock()
delete(sm.m, key)
}

func main() {
sm := NewSafeMap()
sm.Store("foo", 1)
value, ok := sm.Load("foo")
if ok {
fmt.Println("Found:", value)
} else {
fmt.Println("Not found")
}
}


🚩Использование `sync.RWMutex`

sync.RWMutex предоставляет два типа блокировок: для чтения (RLock) и для записи (Lock). Он позволяет нескольким горутинам одновременно читать данные, если нет активных блокировок для записи. Это улучшает производительность в сценариях с частыми операциями чтения и редкими операциями записи.
package main

import (
"fmt"
"sync"
)

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

func NewSafeMap() *SafeMap {
return &SafeMap{
m: make(map[string]int),
}
}

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

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

func (sm *SafeMap) Delete(key string) {
sm.mu.Lock()
defer sm.mu.Unlock()
delete(sm.m, key)
}

func main() {
sm := NewSafeMap()
sm.Store("foo", 1)
value, ok := sm.Load("foo")
if ok {
fmt.Println("Found:", value)
} else {
fmt.Println("Not found")
}
}


🚩Когда использовать `sync.Mutex` и `sync.RWMutex`

🟠`sync.Mutex`:
Используйте, если операции чтения и записи происходят с примерно одинаковой частотой. Подходит для простых сценариев, где производительность не критична.
🟠`sync.RWMutex`:
Используйте, если чтения происходят значительно чаще, чем записи. Улучшает производительность за счет одновременного выполнения нескольких операций чтения.

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

Основные структуры данных в Go включают массивы, слайсы, карты (map) и структуры (struct). Они обеспечивают базовую функциональность для работы с данными. Также доступны каналы для синхронизации между потоками.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что выполняет default в select?

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

🚩Как работает `select` с `default`

Когда select выполняется, он блокируется до тех пор, пока один из его case-блоков не станет готов к выполнению (т.е. канал не станет доступным для отправки или получения данных). Однако, если добавить блок default, select выполнит его немедленно, если ни один из других case-блоков не готов. Это позволяет избежать блокировки горутины и продолжить выполнение других задач.

🚩Пример использования `default` в `select`

package main

import (
"fmt"
"time"
)

func main() {
ch1 := make(chan int)
ch2 := make(chan int)

go func() {
time.Sleep(2 * time.Second)
ch1 <- 1
}()

go func() {
time.Sleep(1 * time.Second)
ch2 <- 2
}()

for i := 0; i < 5; i++ {
select {
case val := <-ch1:
fmt.Println("Received from ch1:", val)
case val := <-ch2:
fmt.Println("Received from ch2:", val)
default:
fmt.Println("No channel is ready")
time.Sleep(500 * time.Millisecond)
}
}
}


1⃣Мы создали два канала ch1 и ch2.
2⃣Две горутины отправляют значения в эти каналы с задержкой.
3⃣В основном цикле используется select с default, который проверяет готовность каналов каждые 500 миллисекунд.
4⃣Если ни один из каналов не готов, выполняется блок default, выводящий сообщение "No channel is ready".

🚩Когда использовать `default` в `select`

🟠Неблокирующие операции
Если вы хотите проверить наличие данных на канале или возможность отправки данных без блокировки, используйте default.
🟠Избежание дедлоков
В некоторых случаях default может предотвратить дедлоки, позволяя горутине продолжить выполнение, даже если каналы временно недоступны.
🟠Проверка состояния канала
Можно использовать default для периодической проверки состояния канала или выполнения задач в ожидании готовности каналов.

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

SOLID — это набор принципов проектирования: единственная ответственность, открытость/закрытость, подстановки Барбары Лисков, разделение интерфейсов и инверсия зависимостей. Эти принципы помогают создавать гибкие, расширяемые и поддерживаемые системы. Они широко применяются в объектно-ориентированном программировании.

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

Мапы (maps) не являются потокобезопасными по умолчанию. Если несколько горутин одновременно пытаются записывать (или читать и записывать) в одну и ту же мапу, это может привести к непредсказуемым результатам, состояниям гонки и даже краху программы (panic).

🚩Пример проблемы

Вот пример, который иллюстрирует проблему конкурентной записи в мапу. В этом примере множество горутин одновременно записывают значения в мапу m, что приведет к состоянию гонки и, возможно, к панике.
package main

import (
"fmt"
"sync"
)

func main() {
m := make(map[int]int)
var wg sync.WaitGroup

for i := 0; i < 100; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
m[i] = i
}(i)
}

wg.Wait()
fmt.Println("Done")
}


🚩Решение проблемы

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

import (
"fmt"
"sync"
)

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

func NewSafeMap() *SafeMap {
return &SafeMap{
m: make(map[int]int),
}
}

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

func (sm *SafeMap) Load(key int) (int, bool) {
sm.mu.Lock()
defer sm.mu.Unlock()
value, ok := sm.m[key]
return value, ok
}

func main() {
sm := NewSafeMap()
var wg sync.WaitGroup

for i := 0; i < 100; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
sm.Store(i, i)
}(i)
}

wg.Wait()

if value, ok := sm.Load(42); ok {
fmt.Println("Found:", value)
} else {
fmt.Println("Not found")
}
}


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

import (
"fmt"
"sync"
)

func main() {
var m sync.Map
var wg sync.WaitGroup

for i := 0; i < 100; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
m.Store(i, i)
}(i)
}

wg.Wait()

if value, ok := m.Load(42); ok {
fmt.Println("Found:", value)
} else {
fmt.Println("Not found")
}
}


🚩Сравнение подходов

🟠sync.Mutex
Позволяет более точный контроль над доступом к мапе. Могут быть использованы для различных структур данных, не только для мап.
🟠sync.Map
Упрощает код, устраняя необходимость в ручной синхронизации. Оптимизирован для сценариев с частыми чтениями и редкими записями.

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

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

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

🟠Мьютексы (`sync.Mutex` и `sync.RWMutex`)
sync.Mutex обеспечивает эксклюзивный доступ для чтения и записи.
sync.RWMutex позволяет одновременное чтение несколькими горутинами и эксклюзивный доступ для записи.
var mu sync.Mutex
var rwMu sync.RWMutex

func increment() {
mu.Lock()
counter++
mu.Unlock()
}

func readCounter() int {
rwMu.RLock()
defer rwMu.RUnlock()
return counter
}


🟠Каналы (`chan`)
Синхронизируют горутины через передачу данных. Буферизованные каналы могут хранить несколько значений, небуферизованные требуют синхронной отправки и получения.
ch := make(chan int, 1)
go func() { ch <- 42 }()
fmt.Println(<-ch)


🟠Группы ожидания (`sync.WaitGroup`)
Позволяют основной горутине ждать завершения всех запущенных горутин.
var wg sync.WaitGroup
wg.Add(1)
go func() { defer wg.Done(); /* работа */ }()
wg.Wait()


🟠Потокобезопасные структуры (`sync.Map`)
Потокобезопасная карта для конкурентного доступа.
var m sync.Map
m.Store("key", "value")
value, ok := m.Load("key")


🟠Одноразовая инициализация (`sync.Once`)
Гарантирует выполнение кода только один раз.
var once sync.Once
once.Do(func() { /* инициализация */ })


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

Карты в Go используют хэш-таблицы для хранения пар ключ-значение. Они хранят данные в бакетах, где каждый бакет может содержать несколько элементов, и используют хэш-функции для доступа к ним. Это обеспечивает быстрый доступ к данным с эффективностью O(1) в среднем случае.

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

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

🚩Виды атомарных операций

🟠Чтение и запись
atomic.LoadInt32, atomic.LoadInt64, atomic.LoadUint32, atomic.LoadUint64, atomic.LoadUintptr
atomic.StoreInt32, atomic.StoreInt64, atomic.StoreUint32, atomic.StoreUint64, atomic.StoreUintptr
var x int32
atomic.StoreInt32(&x, 42)
value := atomic.LoadInt32(&x)


🟠Атомарное добавление
atomic.AddInt32, atomic.AddInt64, atomic.AddUint32, atomic.AddUint64
var x int32
atomic.AddInt32(&x, 1)


🟠Атомарное сравнение и замена (compare-and-swap, CAS)
atomic.CompareAndSwapInt32, atomic.CompareAndSwapInt64, atomic.CompareAndSwapUint32, atomic.CompareAndSwapUint64
var x int32 = 42
swapped := atomic.CompareAndSwapInt32(&x, 42, 100)


🟠Атомарное замена
atomic.SwapInt32, atomic.SwapInt64, atomic.SwapUint32, atomic.SwapUint64
var x int32
old := atomic.SwapInt32(&x, 100)


🟠Атомарные операции над указателями
atomic.LoadPointer, atomic.StorePointer, atomic.SwapPointer, atomic.CompareAndSwapPointer
var ptr unsafe.Pointer
atomic.StorePointer(&ptr, unsafe.Pointer(&x))
p := atomic.LoadPointer(&ptr)


🚩Когда использовать

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

🟠Простые счетчики и флаги
Атомарные операции идеальны для реализации простых счетчиков, флагов или индикаторов состояния.

🟠Низкоуровневый контроль
Когда требуется низкоуровневый контроль над синхронизацией данных без затрат на мьютексы.

package main

import (
"fmt"
"sync"
"sync/atomic"
)

func main() {
var counter int32
var wg sync.WaitGroup

for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
atomic.AddInt32(&counter, 1)
}()
}

wg.Wait()
fmt.Println("Final Counter:", counter)
}


🚩Ограничения и осторожности

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

🟠Чтение и запись сложных структур
Атомарные операции работают с простыми типами данных (числа, указатели). Для сложных структур данных лучше использовать другие механизмы синхронизации.

🟠Трудночитаемость и поддержка кода
Код, использующий атомарные операции, может быть сложнее для понимания и поддержки, особенно если требуются сложные логические операции.

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

Полиморфизм в Go достигается через интерфейсы, которые определяют поведение, а не структуру объектов. Любой тип, который реализует методы интерфейса, может использоваться вместо него. Это позволяет писать гибкий и обобщённый код.

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

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

🟠Управление временем выполнения операций
Контексты позволяют задавать дедлайны и таймауты для операций.
context.WithTimeout создает контекст с таймаутом, после которого операция будет автоматически отменена.
ctx, cancel := context.WithTimeout(parentCtx, 2*time.Second)
defer cancel()


context.WithDeadline создает контекст с дедлайном, который определяет точное время, после которого операция будет отменена.
deadline := time.Now().Add(5 * time.Second)
ctx, cancel := context.WithDeadline(parentCtx, deadline)
defer cancel()


🟠Явная отмена операций
Контексты позволяют явно отменять операции, что полезно для управления горутинами и предотвращения утечек памяти.
context.WithCancel создает контекст, который может быть отменен вручную с помощью функции cancel.
ctx, cancel := context.WithCancel(parentCtx)
defer cancel()


🟠Передача метаданных
Контексты позволяют передавать данные между функциями, что полезно для передачи информации о запросах, пользователей и других данных.
context.WithValue создает контекст, который содержит пару ключ-значение для передачи метаданных.
type key string
ctx := context.WithValue(parentCtx, key("userID"), 12345)


🟠Вложенные контексты
Можно создавать иерархии контекстов, где каждый дочерний контекст наследует отмену и дедлайны от родительского.
Создание вложенных контекстов позволяет строить гибкие и сложные системы управления временем выполнения и отмены.
ctx1, cancel1 := context.WithCancel(parentCtx)
ctx2, cancel2 := context.WithTimeout(ctx1, 1*time.Second)
defer cancel1()
defer cancel2()


🟠Синхронизация горутин
Контексты обеспечивают механизм для синхронизации и координации работы нескольких горутин.
Пример синхронизации горутин
var wg sync.WaitGroup
ctx, cancel := context.WithCancel(parentCtx)
defer cancel()

wg.Add(2)
go func() {
defer wg.Done()
worker(ctx, "Worker 1")
}()
go func() {
defer wg.Done()
worker(ctx, "Worker 2")
}()
wg.Wait()

func worker(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
fmt.Println(name, "stopped")
return
default:
fmt.Println(name, "working")
time.Sleep(1 * time.Second)
}
}
}


🟠Управление жизненным циклом запросов
Контексты широко используются в веб-серверах для управления жизненным циклом HTTP-запросов, обеспечивая таймауты и отмену при завершении обработки запросов.
Пример использования контекста в обработчике HTTP-запроса
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
select {
case <-time.After(5 * time.Second):
fmt.Fprintln(w, "Request processed")
case <-ctx.Done():
err := ctx.Err()
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}

http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Какие бывают типы в Go?

В Go существуют базовые типы (int, float, string, bool), составные типы (массивы, слайсы, карты, структуры), интерфейсы и каналы. Эти типы обеспечивают разнообразие для работы с различными данными. Также можно создавать пользовательские типы на основе существующих.

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

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

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

🟠Родительский контекст
Исходный контекст, от которого создаются дочерние контексты.
🟠Дочерний контекст
Контекст, созданный на основе родительского контекста с дополнительными свойствами, такими как таймаут, дедлайн или значение.

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

🚩Виды контекстов

🟠context.Background()
Корневой контекст без отмены и таймаутов.

🟠context.TODO()
Корневой контекст для временного использования.

🟠context.WithCancel(parent Context)
Создает контекст с возможностью явной отмены.

🟠context.WithTimeout(parent Context, timeout time.Duration)
Создает контекст с таймаутом.

🟠context.WithDeadline(parent Context, d time.Time)
Создает контекст с дедлайном.

🟠context.WithValue(parent Context, key, val interface{})
Создает контекст с добавлением пары ключ-значение.

🚩Пример отмены контекста

Отмена родительского контекста распространяется на дочерние контексты.
package main

import (
"context"
"fmt"
"time"
)

func main() {
// Создаем родительский контекст с возможностью отмены
parentCtx, cancel := context.WithCancel(context.Background())

// Создаем дочерний контекст с таймаутом на основе родительского контекста
ctx, cancelChild := context.WithTimeout(parentCtx, 2*time.Second)
defer cancelChild()

go func() {
// Дочерняя горутина, которая слушает отмену контекста
select {
case <-ctx.Done():
fmt.Println("Child context canceled:", ctx.Err())
}
}()

// Ждем некоторое время и отменяем родительский контекст
time.Sleep(1 * time.Second)
cancel()

// Ждем завершения дочерней горутины
time.Sleep(1 * time.Second)
}


🚩Распространение отмены

🟠Родительский контекст
Когда отменяется родительский контекст, все дочерние контексты (и их дочерние контексты) также отменяются.
🟠Дочерний контекст
Дочерние контексты могут иметь свои собственные условия отмены (например, таймауты), но отмена родительского контекста всегда приводит к отмене всех дочерних.

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

В Go наследование осуществляется через композицию, а не через классическое наследование, как в ООП. Типы могут включать другие типы как вложенные структуры, получая их методы и свойства. Это позволяет избежать жёсткой привязки и повысить гибкость кода.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔Что такое сине-зеленый деплой(blue-green deployment)?

Это метод развертывания приложений, который минимизирует время простоя и снижает риски, связанные с обновлением. Он позволяет плавно переключаться между двумя идентичными средами, называемыми "синей" (blue) и "зеленой" (green).

🚩Основные концепции сине-зеленого деплоя

🟠Две идентичные среды
Синяя среда: (blue environment): Текущая версия приложения, работающая в продакшене.
Зеленая среда
(green environment): Новая версия приложения, готовая к развертыванию.

🟠Переключение трафика
Трафик направляется на одну из сред (синюю или зеленую), в зависимости от того, какая версия приложения должна быть активной.

🟠Обновление
Новая версия приложения развертывается в неактивной среде (например, зеленой). После успешного тестирования переключается трафик на обновленную среду.

🚩Процесс сине-зеленого деплоя

1⃣Подготовка среды
Имеются две идентичные среды: синяя и зеленая. Синяя среда обслуживает текущий трафик пользователей.

2⃣Развертывание новой версии
Новая версия приложения развертывается в зеленой среде, которая в данный момент не принимает пользовательский трафик.

3⃣Тестирование
Зеленая среда тестируется для проверки правильности работы новой версии приложения.

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

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

🚩Преимущества сине-зеленого деплоя

Минимизация времени простоя
Переключение трафика происходит мгновенно, что сводит время простоя к минимуму.

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

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

Снижение рисков
Разделение процессов развертывания и переключения трафика снижает риски, связанные с обновлением.

🚩Пример использования сине-зеленого деплоя

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

1⃣Подготовка зеленой среды
Создаем или обновляем зеленую среду с новой версией приложения.
2⃣Тестирование зеленой среды
Проверяем работу новой версии в зеленой среде, проводим необходимые тесты.
3⃣Переключение трафика
Обновляем настройки балансировщика нагрузки, чтобы направить весь пользовательский трафик на зеленую среду.
4⃣Мониторинг
Следим за состоянием зеленой среды. Если всё работает корректно, зеленая среда остается активной.
5⃣Восстановление в случае ошибки
Если возникают проблемы, переключаем трафик обратно на синюю среду.

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

В Go инкапсуляция достигается через модификаторы доступа, управляемые первой буквой имени: заглавная буква делает элемент экспортируемым (публичным), а строчная — доступным только в пакете (приватным).

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