Найти в Дзене
allaboutknit.ru

Шпоры по Go: все самое нужное в вопрос-ответ

Если вы изучаете Go и готовитесь к практическим задачам, эта шпаргалка — именно то, что нужно. Здесь собраны краткие и ёмкие ответы на ключевые вопросы о памяти, слайсах, строках, map, горутинах и каналах, а также примеры кода для мини-задач. Всё изложено максимально просто: по принципу «вопрос — ответ в одно-два предложения», чтобы вы могли быстро освежить знания или подготовиться к экзамену/тесту. Иерархия памяти: регистры → L1/L2/L3 кэш → RAM → диск.
Как данные попадают в кэш: процессор загружает данные из RAM блоками (кэш-линии).
Кэш-линия: минимальный блок данных в кэше, обычно 64 байта.
False sharing: несколько потоков изменяют разные данные в одной кэш-линии → лишние кэш-мисс. Выравнивание в структурах: компилятор вставляет пустые байты между полями, чтобы соблюсти адрес кратный размеру типа.
Инлайн функций: тело маленькой функции вставляется в место вызова для экономии ресурсов.
Стек vs куча: стек — локальные переменные, быстрое выделение/очистка; куча — динамическая памят
Оглавление

Если вы изучаете Go и готовитесь к практическим задачам, эта шпаргалка — именно то, что нужно. Здесь собраны краткие и ёмкие ответы на ключевые вопросы о памяти, слайсах, строках, map, горутинах и каналах, а также примеры кода для мини-задач. Всё изложено максимально просто: по принципу «вопрос — ответ в одно-два предложения», чтобы вы могли быстро освежить знания или подготовиться к экзамену/тесту.

Память и кэш

Иерархия памяти: регистры → L1/L2/L3 кэш → RAM → диск.

Как данные попадают в кэш: процессор загружает данные из RAM блоками (кэш-линии).

Кэш-линия: минимальный блок данных в кэше, обычно 64 байта.

False sharing: несколько потоков изменяют разные данные в одной кэш-линии → лишние кэш-мисс.

🔹 Go: структуры, стек и куча

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

Инлайн функций: тело маленькой функции вставляется в место вызова для экономии ресурсов.

Стек vs куча: стек — локальные переменные, быстрое выделение/очистка; куча — динамическая память, управляется GC.

Escape analysis: переменная «убежала» из стека в кучу, если её адрес используется вне функции.

Defer: выполняется после return, даже если используется именованный результат.

🔹 Garbage Collector

Garbage collector: автоматически освобождает память, работает параллельно с кодом.

GOGC: процент роста кучи, при котором запускается сборщик мусора.

Размер кучи: память, занятая объектами после последнего обхода GC.

🔹 Слайсы и массивы

Базовый объект в слайсе: указатель на массив, длина и capacity.

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

Массив vs слайс: массив фиксированного размера, слайс — динамический и ссылается на массив.

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

Формула роста capacity:

  • ≤ Go1.13: удвоение до 1024, потом +25%
  • ≥ Go1.18: ×2 до 1024, потом + oldCap/4

🔹 Строки

Почему строки иммутабельные: изменять нельзя; хранятся как указатель + длина на байтовый массив.

Символы в памяти: латиница/ASCII — 1 байт, кириллица UTF-8 — 2–4 байта.

🔹 Map

Устройство map: массив бакетов, в бакетах — ключ-значение; новые версии — Swiss Tables.

Почему нельзя брать адрес элемента map: бакеты могут пересоздаваться при росте map → адрес станет недействительным.

Изменение map во время итерации: неопределенное поведение, может паниковать.

🔹 Горутины и каналы

Горутина vs ОС-поток: легковесная, планируется Go-руntime; может быть тысячи.

Небуферизованный канал: отправка блокируется, пока значение не прочтут; чтение блокируется, пока значение не придет.

Чтение из закрытого канала: возвращает нулевое значение и false для статуса.

sync.Mutex vs sync.RWMutex: RWMutex позволяет нескольким читателям одновременно, Mutex — эксклюзивный.

Атомики (sync/atomic): операции на переменных без блокировок; быстрее, чем мьютексы, но только для примитивов.

🔹 Мини-задачи

Reverse слайса:

func reverse(s []int) []int {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return s
}

Подсчет слов:

func countWords(s string) map[string]int {
counts := make(map[string]int)
for _, w := range strings.Fields(s) {
counts[w]++
}
return counts
}

Канал и close: чтение из закрытого канала — нулевое значение, false для статуса.

Пример горутин с каналом:

ch := make(chan int)
for _, v := range []int{1,2,3} {
go func(val int) { ch <- val }(v)
}
for i := 0; i < 3; i++ { fmt.Println(<-ch) }

Пул воркеров: несколько горутин читают из массива чисел, пишут квадраты в канал.

Сортировка map по ключам:

func mapToSortedList(m map[string]int) []string {
keys := make([]string, 0, len(m))
for k := range m { keys = append(keys, k) }
sort.Strings(keys)
list := make([]string, len(keys))
for i, k := range keys { list[i] = fmt.Sprintf("%s=%d", k, m[k]) }
return list
}