Golang | Вопросы собесов
4.38K subscribers
30 photos
735 links
Download Telegram
🤔 Зачем нужен Prometheus?

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

🚩Почему нужен Prometheus?

🟠Мониторинг состояния системы
позволяет отслеживать производительность, загрузку CPU, память, сетевой трафик и другие параметры.
🟠Автоматический сбор метрик
использует модель pull (запрашивает данные у сервисов), а не push (как, например, Graphite). Это удобнее для управления и отказоустойчивости.
🟠Гибкость в сборе данных
поддерживает кастомные метрики, которые можно интегрировать в своё приложение.
🟠Продвинутая система алертинга
позволяет настроить уведомления при достижении критических значений.
🟠Хранение исторических данных
помогает анализировать тренды и предсказывать возможные сбои.
🟠Масштабируемость
легко развертывается в облаке, Kubernetes, Docker и других средах.

🚩Как работает Prometheus?

🟠Экспортеры метрик
собирают данные.
🟠Prometheus
опрашивает эти экспортеры по HTTP (pull-модель).
🟠PromQL
(язык запросов) используется для анализа данных.
🟠Grafana
или другие инструменты визуализируют метрики.
🟠Alertmanager
отправляет уведомления (Slack, Email, Telegram и др.).

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

Для интеграции в Go-приложение можно использовать пакет prometheus/client_golang
package main

import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

var httpRequests = prometheus.NewCounter(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests",
},
)

func handler(w http.ResponseWriter, r *http.Request) {
httpRequests.Inc() // Увеличиваем счетчик запросов
w.Write([]byte("Hello, Prometheus!"))
}

func main() {
// Регистрируем метрику
prometheus.MustRegister(httpRequests)

// Эндпоинт для сбора метрик
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/", handler)

http.ListenAndServe(":8080", nil)
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
4
🤔 Какие типы мьютексов предоставляет stdlib?

1. sync.Mutex:
- Базовый мьютекс для блокировки доступа к разделяемым данным.
2. sync.RWMutex:
- Поддерживает несколько потоков чтения одновременно, но блокирует запись.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
🤔 Что такое структура (stuct) в Go Зачем они нужны?

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

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

Определяются с использованием ключевого слова struct. В структуре могут быть поля различных типов.
package main

import "fmt"

// Определение структуры Person
type Person struct {
Name string
Age int
}

func main() {
// Создание экземпляра структуры
var p Person
p.Name = "Alice"
p.Age = 30

fmt.Println("Name:", p.Name)
fmt.Println("Age:", p.Age)
}


🚩Инициализация структур

Существует несколько способов инициализации структур.
package main

import "fmt"

// Определение структуры Person
type Person struct {
Name string
Age int
}

func main() {
// Инициализация с использованием литерала структуры
p := Person{Name: "Bob", Age: 25}
fmt.Println("Name:", p.Name)
fmt.Println("Age:", p.Age)
}


Инициализация по умолчанию
package main

import "fmt"

// Определение структуры Person
type Person struct {
Name string
Age int
}

func main() {
// Инициализация по умолчанию (поля будут нулевыми значениями)
var p Person
fmt.Println("Name:", p.Name) // Пустая строка
fmt.Println("Age:", p.Age) // 0
}


🚩Вложенные структуры

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

import "fmt"

// Определение структур Address и Person
type Address struct {
City string
State string
}

type Person struct {
Name string
Age int
Address Address
}

func main() {
// Инициализация структуры с вложенной структурой
p := Person{
Name: "Charlie",
Age: 40,
Address: Address{
City: "New York",
State: "NY",
},
}

fmt.Println("Name:", p.Name)
fmt.Println("Age:", p.Age)
fmt.Println("City:", p.Address.City)
fmt.Println("State:", p.Address.State)
}


🚩Методы структур

Могут быть ассоциированы со структурами, что позволяет добавлять функциональность к структурам.
package main

import "fmt"

// Определение структуры Person
type Person struct {
Name string
Age int
}

// Метод для структуры Person
func (p Person) Greet() {
fmt.Printf("Hello, my name is %s and I am %d years old.\n", p.Name, p.Age)
}

func main() {
p := Person{Name: "David", Age: 35}
p.Greet()
}



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

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

1. Четкость структуры:
- Код становится модульным и более читаемым.
2. Меньшая связность:
- Компоненты проектируются так, чтобы их можно было легко тестировать независимо.
3. Предсказуемость изменений:
- Тесты помогают выявлять ошибки при рефакторинге.


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

Нет, карты (maps) в Go не являются потокобезопасными по умолчанию. Использование карты в нескольких горутинах без должной синхронизации может привести к состояниям гонки, некорректным данным и паникам. Давайте рассмотрим более детально, почему это так и как можно обеспечить потокобезопасность при работе с картами в многопоточной среде.

🚩Почему карты в Go не потокобезопасны

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

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

🚩Подходы к обеспечению потокобезопасности

🟠Мьютексы (Mutex)
Самый распространенный способ синхронизации доступа к карте — использование sync.Mutex. Мьютексы позволяют заблокировать доступ к карте на время чтения или записи.
package main

import (
"fmt"
"sync"
)

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

write := func(key string, value int) {
mu.Lock()
m[key] = value
mu.Unlock()
}

read := func(key string) int {
mu.Lock()
defer mu.Unlock()
return m[key]
}

wg.Add(2)
go func() {
defer wg.Done()
write("key1", 42)
}()
go func() {
defer wg.Done()
fmt.Println(read("key1"))
}()
wg.Wait()
}


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

import (
"fmt"
"sync"
)

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

write := func(key string, value int) {
mu.Lock()
m[key] = value
mu.Unlock()
}

read := func(key string) int {
mu.RLock()
defer mu.RUnlock()
return m[key]
}

wg.Add(2)
go func() {
defer wg.Done()
write("key1", 42)
}()
go func() {
defer wg.Done()
fmt.Println(read("key1"))
}()
wg.Wait()
}


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

import (
"fmt"
"sync"
)

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

wg.Add(2)
go func() {
defer wg.Done()
m.Store("key1", 42)
}()
go func() {
defer wg.Done()
value, _ := m.Load("key1")
fmt.Println(value)
}()
wg.Wait()
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 В чём разница между сцеплением и связанностью?

1. Сцепление (Coupling):
- Мера зависимости между модулями. Сильное сцепление усложняет изменения и тестирование.
2. Связанность (Cohesion):
- Насколько элементы внутри модуля связаны логически. Высокая связанность означает, что модуль выполняет одну задачу.


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

Создание дочернего контекста данных в 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
👍4
🤔 Почему в TDD тесты пишутся прежде кода?

1. Четкость требований:
- Тесты помогают лучше понять, что должен делать код.
2. Минимизация ошибок:
- Код пишется для прохождения тестов, что снижает вероятность багов.
3. Улучшение дизайна:
- Код проектируется так, чтобы быть тестируемым и модульным.


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

1. Сложность изменений:
- Любое изменение требует модификации большого количества частей системы.
2. Высокая связность:
- Модули сильно зависят друг от друга.
3. Дублирование кода:
- Повторяющиеся фрагменты вместо переиспользования.
4. Сложность тестирования:
- Тесты сложно написать или они отсутствуют.


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

1. Файлы:
- Обмен через чтение и запись файлов.
2. Сокеты:
- Используются для связи между процессами по сети или локально.
3. Каналы (Pipes):
- Однонаправленный или двунаправленный обмен данными между процессами.
4. Message Queues:
- Очереди сообщений для асинхронного взаимодействия.
5. Shared Memory:
- Общая память, требующая синхронизации для предотвращения гонок.
6. Сигналы:
- Для отправки уведомлений или сигналов завершения.


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

Интерфейсы имеют ряд уникальных особенностей и отличий от интерфейсов в других языках программирования, таких как Java, C# или C++.

🚩Основные отличия интерфейсов

🟠Неявная реализация интерфейсов
В Go типы реализуют интерфейсы неявно. Это означает, что если тип имеет методы, определенные в интерфейсе, он автоматически считается реализацией этого интерфейса без явного указания.
package main

import "fmt"

type Stringer interface {
String() string
}

type Person struct {
Name string
Age int
}

func (p Person) String() string {
return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func main() {
var s Stringer = Person{Name: "Alice", Age: 30}
fmt.Println(s.String())
}


🟠Отсутствие явного наследования
В Go нет явного наследования интерфейсов или типов. Интерфейсы могут быть составлены из других интерфейсов с помощью композиции, но это не считается наследованием в традиционном смысле.
type Reader interface {
Read(p []byte) (n int, err error)
}

type Writer interface {
Write(p []byte) (n int, err error)
}

type ReadWriter interface {
Reader
Writer
}


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

🟠Малый и простой интерфейс
В Go часто используются маленькие и простые интерфейсы с одним или двумя методами. Это позволяет создавать более гибкие и переиспользуемые компоненты.
type Reader interface {
Read(p []byte) (n int, err error)
}

type Writer interface {
Write(p []byte) (n int, err error)
}


🟠Композиция интерфейсов
Интерфейсы в Go могут быть составлены из других интерфейсов, что позволяет строить сложные интерфейсы из простых.
type Reader interface {
Read(p []byte) (n int, err error)
}

type Writer interface {
Write(p []byte) (n int, err error)
}

type ReadWriter interface {
Reader
Writer
}


🟠Интерфейсы пустого типа
В Go есть специальный пустой интерфейс interface{}, который может содержать значение любого типа. Это делает его мощным инструментом для работы с обобщенным кодом.
func printValue(v interface{}) {
fmt.Println(v)
}

func main() {
printValue(42)
printValue("hello")
printValue(true)
}


🚩Сравнение с другими языками

🟠Java и C#
Интерфейсы в Java и C# требуют явного указания, какие классы реализуют интерфейсы с использованием ключевого слова implements. Явное наследование интерфейсов. Методы доступа часто используются. Интерфейсы могут содержать свойства (в C#), которые требуют реализации.

🟠C++
Интерфейсы часто реализуются с использованием чисто виртуальных функций. Классы должны явно указывать наследование от интерфейсов. Наследование интерфейсов и классов явно указывается.

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

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

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

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

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

🟠Оптимизация алгоритмов и структур данных
Использование более эффективных алгоритмов (например, O(log n) вместо O(n^2)). Выбор подходящих структур данных (например, map вместо срезов для поиска по ключу).

🟠Оптимизация работы с памятью
Снижение количества аллокаций (использование sync.Pool, предварительное выделение памяти). Использование []byte вместо string, если требуется частое изменение строки. Минимизация копирования данных, например, передача []byte по ссылке вместо копирования.

🟠Оптимизация работы с горутинами
Использование worker pool, чтобы избежать избыточного создания горутин. Ограничение количества параллельных задач (runtime.GOMAXPROCS). Использование каналов правильной ёмкости для минимизации блокировок.

🟠Оптимизация ввода-вывода (I/O)
Буферизация (bufio.Reader, bufio.Writer). Использование асинхронных операций при работе с файлами или сетью. Использование io.Pipe() для потоковой обработки данных.

🟠Использование профилирования и анализа производительности
pprof для анализа CPU, памяти и блокировок. race detector (-race флаг) для выявления проблем с конкурентным доступом. Инструменты трассировки (trace).

🚩Пример оптимизации работы с памятью

Пример неэффективного кода
func inefficient() []string {
var result []string
for i := 0; i < 1000; i++ {
result = append(result, fmt.Sprintf("Item %d", i)) // Частые аллокации
}
return result
}


Оптимизированный вариант
func efficient() []string {
result := make([]string, 0, 1000) // Выделяем память заранее
for i := 0; i < 1000; i++ {
result = append(result, fmt.Sprintf("Item %d", i))
}
return result
}


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

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

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

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

🚩Основные агрегатные функции

🟠Сумма (`SUM`)
суммирует все элементы.
🟠Среднее (`AVG`)
вычисляет среднее значение.
🟠Минимум (`MIN`)
находит минимальный элемент.
🟠Максимум (`MAX`)
находит максимальный элемент.
🟠Количество (`COUNT`)
считает количество элементов.

🚩Примеры реализации в Go

Функция суммы (SUM)
func Sum(nums []int) int {
sum := 0
for _, num := range nums {
sum += num
}
return sum
}


Функция среднего (AVG)
func Average(nums []int) float64 {
if len(nums) == 0 {
return 0
}
return float64(Sum(nums)) / float64(len(nums))
}


Функция минимума (MIN)
func Min(nums []int) int {
if len(nums) == 0 {
panic("empty slice")
}
min := nums[0]
for _, num := range nums {
if num < min {
min = num
}
}
return min
}


Функция максимума (MAX)
func Max(nums []int) int {
if len(nums) == 0 {
panic("empty slice")
}
max := nums[0]
for _, num := range nums {
if num > max {
max = num
}
}
return max
}


Функция подсчёта (COUNT)
func Count(nums []int) int {
return len(nums)
}


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

Это стратегия, при которой две версии приложения работают параллельно: одна (blue) обрабатывает текущие запросы, а другая (green) используется для тестирования или подготовки новой версии. После успешного тестирования новая версия переключается на обслуживание пользователей. Это снижает вероятность простоев и ошибок.


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

Тип rune представляет собой alias для типа int32, предназначенного для хранения Unicode кодовых точек.

🚩Зачем он нужен?

🟠Работа с символами Unicode
Строки (string) являются последовательностями байтов, а не символов. Это означает, что один символ может занимать больше одного байта, особенно если это символ из расширенного набора Unicode.
Тип используется для работы с символами, представляемыми одной кодовой точкой Unicode. Это упрощает манипуляции с символами, так как каждая rune — это отдельный символ, независимо от его длины в байтах.

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

🚩Как его использовать ?

Создание и инициализация
      var r rune = '世'
fmt.Println(r) // Output: 19990


Итерация по строке
      s := "Привет, 世界"
for _, r := range s {
fmt.Printf("%c ", r)
}
// Output: П р и в е т , 世 界


Преобразование между string ито такое
      s := "Go"
runes := []rune(s)
fmt.Println(runes) // Output: [71 111]

s2 := string(runes)
fmt.Println(s2) // Output: Go


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
🤔 Что такое Canary (канареечные развертывания)?

Canary deployment предполагает развертывание новой версии приложения на небольшой части пользователей. Если обновление проходит успешно, оно распространяется на всех. Это позволяет минимизировать риски, так как на начальном этапе новая версия тестируется на ограниченном объеме запросов.


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

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

🚩Когда применять Builder?

🟠Сложные объекты
если у объекта много параметров (особенно опциональных).
🟠Читаемость кода
вместо длинного конструктора с кучей аргументов можно вызывать методы-построители.
🟠Иммутабельность
Builder позволяет создать объект инициализированным сразу, без изменения его полей после создания.

🚩Реализация Builder в Go

В Go нет классов, но можно использовать структуры и методы для реализации этого паттерна.
package main

import "fmt"

// Определяем структуру Car
type Car struct {
Brand string
Model string
Color string
Engine string
}

// Определяем "Строителя" для Car
type CarBuilder struct {
car Car
}

// Методы для пошаговой настройки машины
func (cb *CarBuilder) SetBrand(brand string) *CarBuilder {
cb.car.Brand = brand
return cb
}

func (cb *CarBuilder) SetModel(model string) *CarBuilder {
cb.car.Model = model
return cb
}

func (cb *CarBuilder) SetColor(color string) *CarBuilder {
cb.car.Color = color
return cb
}

func (cb *CarBuilder) SetEngine(engine string) *CarBuilder {
cb.car.Engine = engine
return cb
}

// Метод для финальной сборки объекта
func (cb *CarBuilder) Build() Car {
return cb.car
}

// Используем Builder
func main() {
car := CarBuilder{}.
SetBrand("Tesla").
SetModel("Model S").
SetColor("Red").
SetEngine("Electric").
Build()

fmt.Printf("Car: %+v\n", car)
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
🤔 Что такое Dark (скрытые) или А/В-развертывания?

Это скрытое развертывание новой версии приложения без вовлечения реальных пользователей, например, для проверки ее совместимости или производительности. A/B deployment – это развертывание двух разных версий приложения для анализа их эффективности, например, на основе метрик пользовательского поведения.

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

В Go механизм сборки мусора называется Garbage Collector (GC).

🚩Как работает сборщик мусора в Go?

Go использует автоматический сборщик мусора с конкурентной, трицветной, инкрементальной стратегией.

🟠Конкурентный (Concurrent)
выполняется параллельно с работой программы.
🟠Трёхцветный (Tri-color)
объекты помечаются как белые, серые и чёрные.
🟠Инкрементальный (Incremental)
работает порциями, а не останавливает программу надолго.

🚩Алгоритм трёхцветной маркировки

🟠Белые объекты
мусор, который будет удалён.
🟠Серые объекты
те, которые находятся в обработке.
🟠Чёрные объекты
используемые объекты, которые не подлежат удалению.

🚩Оптимизация GC в Go

Чтобы уменьшить нагрузку на GC:
Используйте пул объектов (sync.Pool).
Минимизируйте аллокации в куче (например, используйте []byte вместо string, если можно).
Ограничивайте долгоживущие объекты, так как они реже сканируются.

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