Go runtime — это встроенная среда выполнения, которая управляет памятью, потоками, сборкой мусора и планировщиком горутин. Он делает Go удобным для многопоточного и высоконагруженного программирования без необходимости вручную управлять потоками.
Горутины (goroutines) — лёгкие потоки, управляемые Go.
Планировщик (scheduler) — распределяет горутины по потокам ОС.
Модель памяти — управление стеком и кучей.
Сборщик мусора (GC) — автоматически очищает неиспользуемую память.
Syscalls — взаимодействие с ОС.
Горутины легче, чем потоки ОС: Go может запускать миллионы горутин, а планировщик (M:N) распределяет их по потокам ОС.
Go использует M:N-модель, где:
-
M
— системные потоки (OS threads). -
N
— горутины (goroutines). -
P
— процессоры (logical processors) — управляют выполнением горутин. P
привязан к M
, а G
(горутины) распределяются между `P` динамически. Это позволяет Go эффективно использовать CPU без ручного управления потоками.
Goroutine (G1, G2, G3, ...)
↓
Scheduler → P (Processor) → M (OS Thread) → CPU
Стек (stack) в Go динамический — он начинается с 2 KB и увеличивается при необходимости.
Если стек заполнен, Go автоматически расширяет его.
В отличие от C, Go не требует
malloc/free
, так как есть GC (garbage collector). Go использует автоматический сборщик мусора, который:
Работает параллельно с программой
Минимизирует паузы (low-latency GC)
Очищает неиспользуемые объекты из кучи
import "runtime"
runtime.GC() // Принудительный запуск сборщика мусора (обычно не нужно)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4💊1
Линтеры повышают качество кода, находя ошибки еще на этапе разработки. Это помогает избежать ошибок в продакшене.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
ACID — это набор свойств транзакций в базах данных, обеспечивающий надежность и целостность данных.
Транзакция выполняется либо полностью, либо не выполняется вовсе.
Пример: Если при переводе денег со счета A на счет B ошибка произошла на полпути, изменения откатываются.
Данные остаются в правильном состоянии до и после транзакции.
Пример: Если сумма на всех счетах банка должна оставаться неизменной, транзакция не должна нарушить это правило.
Одновременные транзакции не мешают друг другу.
Пример: Два клиента покупают один и тот же товар, но база данных правильно обрабатывает, кто купил первым.
После завершения транзакции изменения сохраняются, даже если система сломается.
Пример: Если заказ оформлен, он не исчезнет при внезапном отключении электричества.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Захват переменной — это процесс, при котором замыкание получает доступ к переменной, объявленной вне его тела.
Захваченная переменная продолжает жить в памяти, пока замыкание живо, даже если её внешняя область уже вышла из стека.
В Go это может вызывать неожиданные эффекты при захвате переменной цикла, если не делать копию значения внутри тела цикла.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊3👍2
Оптимизация кода в Go может быть выполнена на нескольких уровнях:
Использование более эффективных алгоритмов (например,
O(log n)
вместо O(n^2)
). Выбор подходящих структур данных (например, map
вместо срезов для поиска по ключу). Снижение количества аллокаций (использование
sync.Pool
, предварительное выделение памяти). Использование []byte
вместо string
, если требуется частое изменение строки. Минимизация копирования данных, например, передача []byte
по ссылке вместо копирования. Использование
worker pool
, чтобы избежать избыточного создания горутин. Ограничение количества параллельных задач (runtime.GOMAXPROCS
). Использование каналов правильной ёмкости для минимизации блокировок. Буферизация (
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
👍4
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
В Go методы создаются для структур (или типов) внутри пакета. Это позволяет добавлять логику и поведение объектам.
Допустим, мы создаем пакет
mathutils
, который будет содержать метод для структуры Calculator
.package mathutils
// Calculator - структура с данными
type Calculator struct {
A, B int
}
// Sum - метод для сложения чисел A и B
func (c Calculator) Sum() int {
return c.A + c.B
}
Теперь мы можем использовать этот метод в основном файле программы.
package main
import (
"fmt"
"mypackage/mathutils" // Импортируем наш пакет
)
func main() {
calc := mathutils.Calculator{A: 5, B: 3}
fmt.Println("Sum:", calc.Sum()) // Выведет: Sum: 8
}
Методы можно объявлять как для значений (
func (c Calculator)
) так и для указателей (func (c *Calculator)
). Когда использовать указатели?
Если метод изменяет данные структуры.
Чтобы избежать копирования больших структур.
func (c *Calculator) Multiply(factor int) {
c.A *= factor
c.B *= factor
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Основные типы соединений в SQL:
- INNER JOIN — только совпадающие записи.
- LEFT JOIN — все из левой таблицы, даже без пары.
- RIGHT JOIN — все из правой таблицы.
- FULL OUTER JOIN — всё из обеих таблиц, где возможно — объединяется.
- CROSS JOIN — декартово произведение.
- SELF JOIN — соединение таблицы с самой собой.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Планировщик задач (Scheduler) управляет выполнением процессов и горутин (в случае Go). В контексте операционных систем и языков программирования, таких как Golang, планировщик отвечает за распределение вычислительных ресурсов.
Это легковесный поток, который выполняет код. В отличие от ОС-потоков, она не требует большого количества памяти и управляется рантаймом Go.
Включает стек, контекст выполнения, а также статус (ждёт, выполняется, завершена).
Переключается между потоками ОС прозрачно для разработчика.
Можно создать десятки тысяч горутин без значительных затрат памяти.
go func() {
fmt.Println("Привет из горутины!")
}()
M (Machine) представляет собой реальный поток ОС (kernel thread), на котором выполняются горутины.
Соответствует потокам ОС (
pthread
в Linux, Windows Thread
в Windows). Может одновременно выполнять только одну горутину.
Количество
M
зависит от GOMAXPROCS
, но обычно Go создаёт столько потоков, сколько ядер в системе. runtime.GOMAXPROCS(4) // Использовать 4 ядра процессора
Это сущность, которая отвечает за распределение горутин (
G
) между потоками (M
). P
управляет очередью горутин и раздаёт их потокам (M
). По умолчанию количество
P
равно количеству GOMAXPROCS
. Горутину нельзя выполнить без доступного
P
. [Processor P1] ----> [Machine M1] ----> Выполняет горутины G1, G2
[Processor P2] ----> [Machine M2] ----> Выполняет горутины G3, G4
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊3
map
? Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
Триггер — это специальная процедура в СУБД, которая автоматически выполняется при определённом событии (например,
INSERT
, UPDATE
, DELETE
) в таблице.Когда выполняется определённое действие с таблицей, триггер срабатывает автоматически и выполняет заданную логику. Это полезно для:
- Автоматической проверки данных.
- Поддержания целостности информации.
- Логирования изменений.
Допустим, у нас есть таблица
orders
, и мы хотим автоматически сохранять историю изменений заказов в таблицу orders_log
.CREATE TABLE orders_log (
id SERIAL PRIMARY KEY,
order_id INT,
old_status TEXT,
new_status TEXT,
changed_at TIMESTAMP DEFAULT now()
);
CREATE OR REPLACE FUNCTION log_order_update()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO orders_log (order_id, old_status, new_status)
VALUES (OLD.id, OLD.status, NEW.status);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER order_status_change
AFTER UPDATE ON orders
FOR EACH ROW
WHEN (OLD.status IS DISTINCT FROM NEW.status)
EXECUTE FUNCTION log_order_update();
Используется для проверки или модификации данных перед изменением.
Чаще всего используется для логирования или дополнительных действий.
Позволяет заменить выполнение операции (
INSERT
, UPDATE
, DELETE
).Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
В Go каналы (
chan
) можно закрывать с помощью close(channel)
, чтобы показать, что больше не будет отправляться данных. Как закрыть канал?
ch := make(chan int)
close(ch) // Закрываем канал
Полный пример
package main
import "fmt"
func main() {
ch := make(chan int)
go func() {
for i := 1; i <= 3; i++ {
ch <- i // Отправляем данные
}
close(ch) // Закрываем канал
}()
for val := range ch { // Читаем пока канал не закроется
fmt.Println(val)
}
fmt.Println("Канал закрыт, чтение завершено")
}
Выход
1
2
3
Канал закрыт, чтение завершено
Используем
val, ok := <-ch
: -
ok == true
→ канал открыт, есть данные. -
ok == false
→ канал закрыт. package main
import "fmt"
func main() {
ch := make(chan int)
close(ch)
val, ok := <-ch
fmt.Println("val:", val, "ok:", ok) // val: 0 ok: false
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
В Go механизм сборки мусора называется Garbage Collector (GC).
Go использует автоматический сборщик мусора с конкурентной, трицветной, инкрементальной стратегией.
выполняется параллельно с работой программы.
объекты помечаются как белые, серые и чёрные.
работает порциями, а не останавливает программу надолго.
мусор, который будет удалён.
те, которые находятся в обработке.
используемые объекты, которые не подлежат удалению.
Чтобы уменьшить нагрузку на GC:
Используйте пул объектов (
sync.Pool
). Минимизируйте аллокации в куче (например, используйте
[]byte
вместо string
, если можно). Ограничивайте долгоживущие объекты, так как они реже сканируются.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
HAVING
— это оператор в SQL, который фильтрует группированные (GROUP BY
) данные по агрегатным функциям (SUM
, COUNT
, AVG
, MAX
, MIN
). WHERE
фильтрует отдельные строки до группировки. HAVING
фильтрует группы строк после GROUP BY
. Теперь посчитаем сумму продаж по категориям и оставим только те, где сумма > 250
SELECT category, SUM(amount) AS total_sales
FROM sales
GROUP BY category
HAVING SUM(amount) > 250;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Тип string в Go — это последовательность байтов, закодированных в UTF-8.
Он реализован как структура:
- указатель на массив байтов;
- длина строки.
Строки неизменяемы. Любая операция, которая кажется «изменением», на самом деле создаёт новую строку.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Это целочисленные значения, которые используются для доступа к элементам упорядоченных структур данных. В контексте Go индексы чаще всего применяются для работы со строками, массивами, срезами, а также картами (косвенно, через ключи).
Индексы позволяют обращаться к конкретным элементам массива, строки или среза. Например, если у нас есть массив чисел, индекс указывает, какой именно элемент извлечь.
С помощью индексов можно перебирать элементы массива, строки или среза, например, используя циклы.
В изменяемых структурах данных, таких как срезы или массивы, индекс позволяет присвоить новое значение конкретному элементу.
Индексы упрощают и ускоряют доступ к данным, потому что доступ осуществляется за O(1) (константное время) в массивах или срезах.
В строках индексы используются для доступа к конкретным байтам.
package main
import "fmt"
func main() {
str := "Привет"
fmt.Println(str[0]) // 208 (байт, не символ!)
fmt.Printf("%c\n", str[0]) // П (символ, представленный первым байтом UTF-8)
}
В массивах и срезах индексы используются для извлечения и изменения значений
package main
import "fmt"
func main() {
arr := [5]int{10, 20, 30, 40, 50}
fmt.Println(arr[2]) // 30
// Изменение значения по индексу
arr[2] = 100
fmt.Println(arr) // [10 20 100 40 50]
}
Обычно индексы используются для итерации по элементам коллекции с помощью цикла
for
.package main
import "fmt"
func main() {
nums := []int{10, 20, 30, 40, 50}
for i, v := range nums {
fmt.Printf("Индекс: %d, Значение: %d\n", i, v)
}
}
Индексы полезны для извлечения подстрок с использованием срезов:
package main
import "fmt"
func main() {
str := "Привет, Мир!"
fmt.Println(str[8:12]) // Мир
}
Если попытаться обратиться к элементу по индексу, который выходит за пределы коллекции, Go выдаст runtime panic:
package main
func main() {
nums := []int{1, 2, 3}
fmt.Println(nums[5]) // panic: runtime error: index out of range
}
Если неверно учитывать байтовое представление символов UTF-8, можно получить некорректный результат.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
- Фиксировать транзакции быстрее – минимизировать время блокировки.
- Обращаться к таблицам в одном порядке во всех транзакциях.
- Использовать LOCK TABLES осторожно – избегать чрезмерного блокирования.
- Рассмотреть уровень изоляции – READ COMMITTED или REPEATABLE READ могут уменьшить вероятность дедлоков.
- Анализировать логи и SHOW ENGINE INNODB STATUS для выявления конфликтов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥2