Golang | Вопросы собесов
4.35K subscribers
26 photos
1 video
714 links
Download Telegram
Forwarded from easyoffer
💡 В EasyOffer 2.0 появится фильтрация вопросов по грейдам и типам интервью!

📊 Например, вот вероятности ТОП-30 вопросов, которые задают на HR-скрининге Python-разработчику уровня Middle/Senior. Данные основаны на 53 реальных интервью.

97% Какие у тебя зарплатные ожидания
73% Какие у тебя есть вопросы
44% Какие критерии при выборе будущей работы
41% Расскажи о себе
38% Почему ищешь работу
35% Расскажи про свой опыт
35% Расскажи про проект на предыдущей работе
32% Почему уволился с предыдущей работы
29% Где территориально сейчас живешь/находишься
23% Есть ли другие предложения по работе
17% Есть ли военный билет
17% Почему хочешь сменить работу
17% Как проводишь свободное время
17% Расскажи про задачи на предыдущей работе
17% Сколько коммерческого опыта работы с Python
17% С какими БД работал
14% Находишься ли в активном поиске работы
14% С каким стеком работаешь
14% Почему решил откликнуться на нашу вакансию
14% Какой текущий статус поиска работы
11% Почему решил стать программистом
11% С какими фреймворками работал
11% Какую зарплату получал на предыдущей работе
11% Работаешь ли в настоящий момент
11% На какой грейд себя оцениваешь
11% Как быстро можешь приступить к работе после получения офера
11% Расскажи про свои pet-проекты
8% Какие знаешь типы данных в Python
8% Что такое декоратор в Python
8% Что ищешь на новой работе

🚀 Скоро стартует краудфандинговая кампания, которая поможет ускорить разработку EasyOffer 2.0.
Первые спонсоры получат уникальные лимитированные награды!

📢 Если вам это интересно, подписывайтесь на канал 👉 этот телеграм канал
🤔 Что такое SLI?

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

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

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

🚩Пустой интерфейс

Поскольку пустой интерфейс не требует реализации каких-либо методов, любой тип в Go автоматически реализует этот интерфейс. Это делает пустой интерфейс универсальным контейнером для значений любых типов.
type interface{} interface {}


🚩Внутреннее представление интерфейсов в Go

🟠Type
Типа конкретного значения
🟠Value
Самого значения

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

🚩Приведение пустого интерфейса к конкретному типу

Когда значение из пустого интерфейса приводится к конкретному типу, происходит проверка типа во время выполнения. Если значение внутри интерфейса действительно является указанным типом, приведение успешно. В противном случае приведение не удается, и возвращается значение nil или происходит паника, если приведение выполнено без проверки.

Присваивание значений пустому интерфейсу
package main

import "fmt"

func main() {
var i interface{}
i = 42
fmt.Println(i) // 42

i = "hello"
fmt.Println(i) // hello
}


Утверждение типа (Type Assertion)
package main

import "fmt"

func main() {
var i interface{} = "hello"

// Утверждение типа с проверкой
s, ok := i.(string)
if ok {
fmt.Println("String:", s)
} else {
fmt.Println("Not a string")
}

// Утверждение типа без проверки
// Это вызовет панику, если тип не соответствует
s = i.(string)
fmt.Println("String:", s)
}


Использование switch для проверки типа
package main

import "fmt"

func printType(i interface{}) {
switch v := i.(type) {
case string:
fmt.Println("String:", v)
case int:
fmt.Println("Integer:", v)
case bool:
fmt.Println("Boolean:", v)
default:
fmt.Printf("Unknown type: %T\n", v)
}
}

func main() {
printType("hello")
printType(42)
printType(true)
printType(3.14)
}


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

К популярным инструментам CI/CD относятся Jenkins, GitLab CI/CD, GitHub Actions, CircleCI, Travis CI и Azure DevOps. Эти инструменты помогают автоматизировать сборку, тестирование, развертывание и мониторинг приложений.

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

В Go строки представлены как набор байтов ([]byte), но количество символов может отличаться, так как некоторые символы занимают несколько байтов (например, Unicode).

🚩Способы подсчёта символов в строке

len(s) – количество байтов (НЕ символов!)
s := "Привет"
fmt.Println(len(s)) // 12, потому что кириллические символы занимают 2 байта

utf8.RuneCountInString(s) – количество символов (РЕКОМЕНДУЕТСЯ )
package main

import (
"fmt"
"unicode/utf8"
)

func main() {
s := "Привет"
fmt.Println(utf8.RuneCountInString(s)) // 6, правильно считает символы
}


Подсчёт через range (альтернативный метод)
count := 0
for range "Привет" {
count++
}
fmt.Println(count) // 6


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

Для обеспечения стабильности используются методы развертывания (например, blue-green или canary deployment), интеграция тестирования в CI/CD pipeline и инструменты мониторинга. Также важны автоматические откаты на предыдущую версию в случае ошибок.

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

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

🚩Императивное программирование

Это стиль программирования, где выражается последовательность команд для выполнения задач. В этом подходе программист указывает машине, как изменять своё состояние пошагово, контролируя поток выполнения через управляющие конструкции, такие как циклы, условные операторы и т.д.
🟠Подробное описание процесса
Программист должен указывать все шаги, которые необходимо выполнить для достижения результата.
🟠Примеры языков
Java, C, Python в их традиционном использовании.
🟠Управление состоянием
Императивные программы часто включают явное управление состоянием и его изменениями.
# Императивный подход к сортировке массива методом пузырька
def bubble_sort(array):
n = len(array)
for i in range(n):
for j in range(0, n-i-1):
if array[j] > array[j+1]:
array[j], array[j+1] = array[j+1], array[j]
return array


🚩Декларативное программирование

Это стиль программирования, где описывается желаемый результат, но не детализируется процесс его достижения. В декларативном стиле программа определяет, что должно быть сделано, а не как.
🟠Абстракция от процесса
Описываются желаемые свойства результата, а система сама определяет, как его достичь.
🟠Примеры языков
SQL, HTML, CSS, функциональные языки программирования, такие как Haskell.
🟠Сокрытие сложности
Декларативный подход часто предполагает высокий уровень абстракции, что уменьшает количество деталей, которые нужно учитывать.

-- Декларативный запрос в SQL для получения списка сотрудников, отсортированного по зарплате
SELECT name, salary FROM employees ORDER BY salary DESC;


🚩Основные различия

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

🟠Управление состоянием
Императивный подход требует активного управления состоянием программы, в то время как в декларативном подходе состояние управляется системой или вовсе абстрагировано.

🟠Поддержка языка
Разные языки поддерживают разные стили программирования. Некоторые языки, как JavaScript, могут поддерживать оба стиля в зависимости от использования.

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

Часто встречаются проблемы с некорректными конфигурациями, зависимостями или ошибками в коде. Для их решения используют автоматизацию через CI/CD, предварительное тестирование, настройку мониторинга и механизм откатов. Например, в случае ошибки новая версия может быть заменена предыдущей без длительного простоя.


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


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

🚩Композиция

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

import "fmt"

// Определение структуры
type Engine struct {
Power int
}

func (e Engine) Start() {
fmt.Println("Engine started with power:", e.Power)
}

// Определение другой структуры, которая включает первую
type Car struct {
Brand string
Engine
}

func main() {
myCar := Car{
Brand: "Toyota",
Engine: Engine{Power: 150},
}

fmt.Println("Car brand:", myCar.Brand)
myCar.Start() // Вызов метода встроенной структуры
}


🚩Интерфейсы

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

import "fmt"

// Определение интерфейса
type Drivable interface {
Drive()
}

// Определение структуры, реализующей интерфейс
type Car struct {
Brand string
}

func (c Car) Drive() {
fmt.Println(c.Brand, "is driving")
}

// Еще одна структура, реализующая интерфейс
type Bike struct {
Brand string
}

func (b Bike) Drive() {
fmt.Println(b.Brand, "is driving")
}

// Функция, принимающая интерфейс
func StartDriving(d Drivable) {
d.Drive()
}

func main() {
car := Car{Brand: "Toyota"}
bike := Bike{Brand: "Yamaha"}

StartDriving(car)
StartDriving(bike)
}


🚩Встраивание интерфейсов

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

import "fmt"

// Определение базового интерфейса
type Printer interface {
Print()
}

// Определение другого интерфейса, включающего первый
type AdvancedPrinter interface {
Printer
Scan()
}

// Реализация структуры, реализующей расширенный интерфейс
type MultiFunctionPrinter struct{}

func (m MultiFunctionPrinter) Print() {
fmt.Println("Printing...")
}

func (m MultiFunctionPrinter) Scan() {
fmt.Println("Scanning...")
}

func main() {
mfp := MultiFunctionPrinter{}
mfp.Print()
mfp.Scan()
}


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

Тип интерфейса проверяется с помощью type assertion (утверждения типа) или оператора switch. Например, в Go это позволяет выяснить, к какому конкретному типу относится переменная, реализующая интерфейс.

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

Prometheus – это мощная система мониторинга с временными рядами (time series), которая собирает метрики из сервисов, хранит их и позволяет строить графики и отправлять алерты.

🚩Ключевые особенности Prometheus

Pull-модель – сам запрашивает метрики у сервисов (в отличие от push-модели, как в StatsD).
Формат временных рядов – каждая метрика привязана ко времени и меткам (labels).
Язык запросов PromQL – позволяет анализировать и агрегировать метрики.
Автодетектирование сервисов – поддержка Kubernetes, Docker, Consul.
Хранение данных в базе TSDB (Time Series Database).
Гибкая система алертов – интеграция с Alertmanager (уведомления в Slack, Telegram и др.).

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

Экспортеры/сервисы предоставляют метрики через HTTP-эндпоинт (/metrics).
Prometheus сам запрашивает данные по расписанию.
Метрики хранятся в базе TSDB.
Можно строить графики в Grafana или запрашивать данные через API.
Алерты отправляются в Alertmanager при достижении пороговых значений.

🚩Пример метрик в Go
Go-сервис может отдавать метрики через HTTP с помощью 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 main() {
// Регистрируем метрику
prometheus.MustRegister(httpRequests)

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

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

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


Пример запроса в PromQL
http_requests_total


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

Пустой интерфейс (interface{} в Go) может содержать значения любого типа, так как не накладывает никаких ограничений на структуру данных. Он используется как универсальный контейнер.

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

Паттерн "Очередь" (Queue) в программировании обычно представляет собой структуру данных или архитектурный подход, используемый для обработки сообщений, задач или запросов в определённом порядке (обычно FIFO — "первым вошёл, первым вышел").
Но если рассматривать количество очередей в каком-то конкретном паттерне проектирования, то всё зависит от контекста. Например:

🚩Одиночная очередь (Single Queue)

Все задачи обрабатываются в одной очереди по порядку. Используется, когда важен строгий порядок выполнения. Пример: канал (channel) в Go, куда отправляются задачи для обработки.

🚩Несколько очередей (Multiple Queues)

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

🚩Очередь с пуулом воркеров (Worker Pool Queue)

Есть одна очередь задач, но несколько рабочих (goroutines), которые извлекают задачи и обрабатывают их параллельно.
Уменьшает нагрузку на систему и ускоряет выполнение.
     package main

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

func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
for job := range jobs {
fmt.Printf("Worker %d started job %d\n", id, job)
time.Sleep(time.Second) // имитация работы
fmt.Printf("Worker %d finished job %d\n", id, job)
results <- job * 2
}
}

func main() {
jobs := make(chan int, 5)
results := make(chan int, 5)
var wg sync.WaitGroup

numWorkers := 3
for i := 1; i <= numWorkers; i++ {
wg.Add(1)
go worker(i, jobs, results, &wg)
}

for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)

wg.Wait()
close(results)

for res := range results {
fmt.Println("Result:", res)
}
}


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

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

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

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

🟠Примитивные типы
числа, строки, булевы значения и т.д.
🟠Композитные типы
массивы, срезы, карты, структуры.
🟠Функции
функции различных типов.
🟠Другие интерфейсы
значения, которые реализуют другие интерфейсы.

🚩Примеры

Примитивные типы
package main

import "fmt"

func main() {
var i interface{}
i = 42
fmt.Println(i) // Output: 42

i = "hello"
fmt.Println(i) // Output: hello

i = true
fmt.Println(i) // Output: true
}


Композитные типы
package main

import "fmt"

func main() {
var i interface{}

i = []int{1, 2, 3}
fmt.Println(i) // Output: [1 2 3]

i = map[string]int{"one": 1, "two": 2}
fmt.Println(i) // Output: map[one:1 two:2]

type Person struct {
Name string
Age int
}

i = Person{Name: "Alice", Age: 30}
fmt.Println(i) // Output: {Alice 30}
}


Функции
package main

import "fmt"

func main() {
var i interface{}

i = func() {
fmt.Println("Hello from function")
}

if f, ok := i.(func()); ok {
f() // Output: Hello from function
}
}


Другие интерфейсы
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 i interface{}

i = Person{Name: "Alice", Age: 30}

if str, ok := i.(Stringer); ok {
fmt.Println(str.String()) // Output: Alice (30 years old)
}
}


🚩Проверка и приведение типа

Утверждение типа
package main

import "fmt"

func main() {
var i interface{} = 42

if v, ok := i.(int); ok {
fmt.Println("Integer:", v) // Output: Integer: 42
} else {
fmt.Println("Not an integer")
}
}


Использование switch для проверки типа
package main

import "fmt"

func printType(i interface{}) {
switch v := i.(type) {
case string:
fmt.Println("String:", v)
case int:
fmt.Println("Integer:", v)
case bool:
fmt.Println("Boolean:", v)
default:
fmt.Printf("Unknown type: %T\n", v)
}
}

func main() {
printType("hello") // Output: String: hello
printType(42) // Output: Integer: 42
printType(true) // Output: Boolean: true
printType(3.14) // Output: Unknown type: float64
}


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

Это инструмент для визуализации метрик и логов. Он позволяет строить графики, панели мониторинга и алерты на основе данных из Prometheus, InfluxDB, Loki и других источников.


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

Замыкание (closure) — это функция, которая запоминает и использует переменные из своей внешней области видимости, даже если эта область видимости уже закончила своё выполнение.

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

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

import "fmt"

func counter() func() int {
count := 0
return func() int {
count++
return count
}
}

func main() {
inc := counter() // создаём замыкание
fmt.Println(inc()) // 1
fmt.Println(inc()) // 2
fmt.Println(inc()) // 3

newInc := counter() // новое замыкание с новой переменной count
fmt.Println(newInc()) // 1
}


🚩Где полезно использовать?

Счётчики (как в примере выше). Фабричные функции, создающие специфичные обработчики. Ограничение доступа к данным (инкапсуляция).

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Зачем нужен Prometheus?

Это система мониторинга и алертинга, разработанная для сбора метрик в реальном времени. Он хранит данные в timeseries формате и предоставляет мощный язык запросов (PromQL) для анализа.


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

В Go срезы (slice) динамически изменяемы, и при добавлении новых элементов их вместимость (capacity) увеличивается по определённому алгоритму.

🚩Как растёт `slice` в Go?

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

🚩Алгоритм роста:

Если cap(slice) < 1024, то новая ёмкость (capacity) удваивается.
Если cap(slice) >= 1024, то увеличение идёт примерно на 25% от текущего размера.

package main

import "fmt"

func main() {
var s []int
prevCap := cap(s)

for i := 0; i < 20; i++ {
s = append(s, i)
if cap(s) != prevCap {
fmt.Printf("Len: %d, New Cap: %d (growth: %.2fx)\n", len(s), cap(s), float64(cap(s))/float64(prevCap))
prevCap = cap(s)
}
}
}


Выходные данные (может отличаться в зависимости от реализации Go)
Len: 1, New Cap: 1 (growth: Inf)
Len: 2, New Cap: 2 (growth: 2.00x)
Len: 3, New Cap: 4 (growth: 2.00x)
Len: 5, New Cap: 8 (growth: 2.00x)
Len: 9, New Cap: 16 (growth: 2.00x)
Len: 17, New Cap: 32 (growth: 2.00x)


🚩Почему так?

🟠Экономия памяти
если бы рост был на 1 элемент, то это вызывало бы частые копирования.
🟠Скорость работы
экспоненциальный рост уменьшает количество выделений памяти.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Зачем нужна Grafana?

Grafana нужна для гибкой визуализации данных из Prometheus и других хранилищ. Она позволяет:
- Создавать интерактивные панели мониторинга.
- Настраивать уведомления (alerts).
- Подключаться к разным источникам данных.


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

Да, знаком. 12FA (12-Factor App) — это набор принципов, созданных разработчиками Heroku для построения масштабируемых, надежных и удобных в развертывании SaaS-приложений. Эти принципы особенно полезны при разработке облачных сервисов (Cloud-Native).

🚩Основные 12 факторов

🟠Кодовая база (Codebase)
У приложения должна быть единая кодовая база (один репозиторий), независимо от количества развертываний (production, staging, dev).

🟠Зависимости (Dependencies)
Все зависимости должны явно указываться в go.mod / go.sum (для Go). Никаких глобальных зависимостей в системе.

🟠Конфигурация (Config)
Конфигурация должна храниться в переменных окружения, а не в коде.
export DATABASE_URL="postgres://user:pass@host:5432/db"


🟠Бэкенд-сервисы (Backing Services)
Внешние сервисы (БД, кэш, API) должны быть заменяемыми и подключаться через URL (без хардкода).

🟠Постоянная сборка, запуск и запуск (Build, Release, Run)
Сборка, релиз и запуск должны быть разделены. Например, Docker-контейнеры для каждой стадии.

🟠Процессы (Processes)
Приложение должно быть бесстатичным (не хранить файлы локально, использовать БД, S3 и т. д.).

🟠Привязка портов (Port Binding)
Приложение должно быть самодостаточным и слушать порт (например, через http.ListenAndServe).

🟠Параллелизм (Concurrency)
Масштабируемость должна обеспечиваться горизонтальным масштабированием (разделением на процессы).

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

🟠Совместимость Dev/Prod (Dev/Prod Parity)
Среды разработки и продакшена должны быть максимально похожи.

🟠Логирование (Logs)
Логи должны писаться в стандартный вывод и обрабатываться внешними системами (ELK, Loki, Grafana).

🟠Админ-процессы (Admin Processes)
Скрипты администрирования (миграции, отладка) должны выполняться как отдельные процессы.

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