Golang | Вопросы собесов
4.55K subscribers
29 photos
856 links
Download Telegram
🤔 Как работает append в слайсе ?

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

🚩Как он работает

🟠Если емкости достаточно
Если текущий подлежащий массив слайса имеет достаточно места (емкости) для добавления новых элементов, append просто добавляет элементы к существующему массиву.
🟠Если емкости недостаточно
Если емкость текущего массива недостаточна для размещения новых элементов, append выделяет новый массив, копирует в него существующие элементы и добавляет новые элементы. Новый массив будет иметь увеличенную емкость (как правило, в два раза больше, чем предыдущая).

Синтаксис
slice = append(slice, elem1, elem2, ...)


Пример использования
package main

import "fmt"

func main() {
// Создаем слайс из 3 целых чисел
slice := []int{1, 2, 3}

// Добавляем один элемент
slice = append(slice, 4)

// Добавляем несколько элементов
slice = append(slice, 5, 6, 7)

// Выводим слайс
fmt.Println(slice) // Выводит: [1 2 3 4 5 6 7]
}


🚩Объяснение работы

1⃣Начальный слайс
Создаем слайс с тремя элементами [1, 2, 3].
slice := []int{1, 2, 3}   


2⃣Добавление одного элемента
Добавляем элемент 4 к слайсу. Теперь слайс содержит [1, 2, 3, 4].
slice = append(slice, 4)   


3⃣Добавление нескольких элементов
Добавляем элементы 5, 6, и 7. Теперь слайс содержит [1, 2, 3, 4, 5, 6, 7].
slice = append(slice, 5, 6, 7)   


4⃣Вывод слайса
Выводим слайс, который содержит [1, 2, 3, 4, 5, 6, 7].
fmt.Println(slice)   


Работа с емкостью и длиной
package main

import "fmt"

func main() {
slice := []int{1, 2, 3}
fmt.Printf("Before append: len=%d cap=%d %v\n", len(slice), cap(slice), slice)

slice = append(slice, 4)
fmt.Printf("After append: len=%d cap=%d %v\n", len(slice), cap(slice), slice)

slice = append(slice, 5, 6, 7)
fmt.Printf("After multiple appends: len=%d cap=%d %v\n", len(slice), cap(slice), slice)
}


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

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

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

Триггер — это специальная процедура в СУБД, которая автоматически выполняется при определённом событии (например, INSERT, UPDATE, DELETE) в таблице.

🚩Как работают триггеры?

Когда выполняется определённое действие с таблицей, триггер срабатывает автоматически и выполняет заданную логику. Это полезно для:
- Автоматической проверки данных.
- Поддержания целостности информации.
- Логирования изменений.

🚩Пример триггера в PostgreSQL

Допустим, у нас есть таблица 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();


🚩Разновидности триггеров

🟠До выполнения операции (`BEFORE`)
Используется для проверки или модификации данных перед изменением.

🟠После выполнения операции (`AFTER`)
Чаще всего используется для логирования или дополнительных действий.

🟠INSTEAD OF (для представлений)
Позволяет заменить выполнение операции (INSERT, UPDATE, DELETE).

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

Ключи должны быть сравнимыми типами, которые можно проверять на равенство.
1. Допустимые типы:
- Примитивы: int, float, string, bool.
- Указатели.
- Структуры, если все их поля имеют сравнимые типы.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Forwarded from easyoffer
Официальный релиз easyoffer 2.0 состоится уже в течение нескольких дней.

Напоминаю, что в честь релиза запускаем акцию.

Первые 500 покупателей получат:

🚀 Скидку 50% на PRO тариф на 1 год
🎁 Подарок ценностью 5000₽ для тех, кто подписан на этот канал

🔔 Подпишитесь на этот канал: https://t.me/+b2fZN17A9OQ3ZmJi
В нем мы опубликуем сообщение о релизе в первую очередь
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое тип 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
👍2🔥1
🤔 Что такое интерфейсы?

Интерфейсы в Go — это набор методов, которые должны быть реализованы типом для соответствия этому интерфейсу. Типы в Go не требуют явного указания реализации интерфейса; достаточно реализовать все его методы. Интерфейсы позволяют создавать гибкие и расширяемые программы, поддерживающие полиморфизм. Интерфейсы широко используются для создания общих алгоритмов и структур данных.

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

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

🚩Основные характеристики

🟠Фиксированный размер
Размер массива задается при его объявлении и не может изменяться во время выполнения программы.
🟠Тип элементов
Все элементы массива имеют один и тот же тип.
🟠Непрерывное размещение в памяти
Элементы массива хранятся последовательно в памяти, что обеспечивает быстрый доступ к любому элементу по индексу.

🚩Объявление и инициализация массивов

Массивы объявляются с указанием типа элементов и фиксированного размера:
var arr [5]int


🟠Инициализация массива
Могут быть инициализированы при объявлении:
arr := [5]int{1, 2, 3, 4, 5}


Можно также инициализировать массив частично, оставив остальные элементы равными нулям:
arr := [5]int{1, 2}


🟠Доступ к элементам массива
Осуществляется с использованием индексов, начиная с 0:
fmt.Println(arr[0]) // 1
arr[1] = 10
fmt.Println(arr[1]) // 10


🟠Длина массива
Фиксирована и задается при его объявлении. Ее можно получить с помощью функции len:
fmt.Println(len(arr)) // 5


🟠Копирование массива
При присваивании одного массива другому копируются все элементы:
arr1 := [5]int{1, 2, 3, 4, 5}
arr2 := arr1
arr2[0] = 10
fmt.Println(arr1) // [1 2 3 4 5]
fmt.Println(arr2) // [10 2 3 4 5]


🟠Передача массива в функции
Копируется весь массив:
func modifyArray(a [5]int) {
a[0] = 10
}

arr := [5]int{1, 2, 3, 4, 5}
modifyArray(arr)
fmt.Println(arr) // [1 2 3 4 5]


🟠Сравнение массивов
С помощью оператора ==, если они имеют одинаковую длину и тип элементов:
arr1 := [3]int{1, 2, 3}
arr2 := [3]int{1, 2, 3}
arr3 := [3]int{4, 5, 6}

fmt.Println(arr1 == arr2) // true
fmt.Println(arr1 == arr3) // false


Пример
package main

import (
"fmt"
)

func main() {
// Объявление и инициализация массива
arr := [5]int{1, 2, 3, 4, 5}

// Доступ к элементам
fmt.Println("First element:", arr[0]) // First element: 1

// Изменение элементов
arr[1] = 10
fmt.Println("Modified array:", arr) // Modified array: [1 10 3 4 5]

// Длина массива
fmt.Println("Length of array:", len(arr)) // Length of array: 5

// Копирование массива
arr2 := arr
arr2[0] = 20
fmt.Println("Original array:", arr) // Original array: [1 10 3 4 5]
fmt.Println("Copied array:", arr2) // Copied array: [20 10 3 4 5]

// Передача массива в функцию
modifyArray(arr)
fmt.Println("Array after modifyArray call:", arr) // Array after modifyArray call: [1 10 3 4 5]
}

func modifyArray(a [5]int) {
a[0] = 10
}


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

В map ключи должны быть сравнимыми, то есть поддерживать операцию сравнения ==. Это означает, что в качестве ключей можно использовать типы, такие как string, int, float, bool, array, pointer, struct (если все его поля сравнимы). Нельзя использовать slice, map, function в качестве ключей, так как они не поддерживают сравнение.

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

HTTP (HyperText Transfer Protocol) — это протокол, используемый для передачи данных в интернете.

🚩Основные версии HTTP.

🟠HTTP/0.9
Год выпуска: 1991

Особенности
Первая версия HTTP, очень простая. Поддерживала только GET-запросы. Отсутствие заголовков, только один объект мог быть передан в ответ на запрос.

Использование:
В настоящее время практически не используется.

🟠HTTP/1.0
Год выпуска: 1996

Особенности
Введены методы запроса, такие как GET, POST и HEAD. Поддержка заголовков для метаданных. Каждый запрос/ответ требует нового соединения, что делает передачу данных менее эффективной.

Использование
Исторически важен, но также почти не используется в современных приложениях.

🟠HTTP/1.1
Год выпуска: 1997

Особенности
Поддержка устойчивых (persistent) соединений, что позволяет повторное использование одного соединения для нескольких запросов/ответов. Введены дополнительные методы запросов, такие как OPTIONS, PUT, DELETE, TRACE и CONNECT. Поддержка chuncked transfer encoding для передачи данных по частям. Улучшена работа с кэшированием и аутентификацией.

Использование
Широко используется и в настоящее время, хотя многие системы переходят на HTTP/2.

🟠HTTP/2
Год выпуска: 2015

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

Использование
Быстро набирает популярность благодаря улучшенной производительности и эффективности.

🟠HTTP/3
Год выпуска: 2022 (черновая версия в 2020)

Особенности
Основан на протоколе QUIC, который работает поверх UDP, а не TCP. Поддержка улучшенного мультиплексирования и быстрого установления соединений. Лучшая устойчивость к потерям пакетов и более высокая скорость передачи данных по сравнению с HTTP/2.

Использование
Внедрение продолжается, но многие крупные интернет-компании, такие как Google и Facebook, уже активно используют HTTP/3.

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

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


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Безопасен ли 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
👍3
🤔 Что можешь сказать о HTTP3?

HTTP/3, работающий на основе QUIC, обеспечивает быструю передачу данных поверх UDP. Для его использования в Go можно применять библиотеки вроде quic-go, позволяющие интегрировать поддержку HTTP/3.


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

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

🚩Задача

В моём проекте был сервис, который обрабатывал тысячи файлов параллельно. Если запускать новую горутину на каждый файл, то память быстро заканчивалась, и сервер "умирал".
Решение: вместо создания тысяч горутин я использовал Worker Pool с фиксированным числом воркеров (например, 5), которые брали задачи из очереди.

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

Есть канал задач (jobs).
Есть пул воркеров (workers), которые читают задачи из канала.
Каждый воркер обрабатывает одну задачу и берёт следующую.
package main

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

// Количество воркеров
const workerCount = 5

// Воркер, который берет задачи из канала и обрабатывает их
func worker(id int, jobs <-chan int, wg *sync.WaitGroup) {
defer wg.Done()
for job := range jobs {
fmt.Printf("Worker %d processing job %d\n", id, job)
time.Sleep(time.Second) // Имитация обработки
}
}

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

// Запускаем воркеров
for i := 1; i <= workerCount; i++ {
wg.Add(1)
go worker(i, jobs, &wg)
}

// Отправляем задачи в канал
for j := 1; j <= 10; j++ {
jobs <- j
}
close(jobs) // Закрываем канал, чтобы воркеры знали, что задачи кончились

wg.Wait() // Ждём завершения всех воркеров
fmt.Println("Все задачи обработаны")
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊3👍2🤔1
🤔 Для чего нужны оконные функции?

Оконные функции (window functions) — это SQL-функции, которые выполняются по строкам с учётом контекста «окна» (группы строк).
Примеры использования:
- Нумерация (ROW_NUMBER())
- Скользящие суммы/средние (SUM() OVER(...))
- Сравнение соседних строк (LAG(), LEAD())
- Ранжирование (RANK())
Они позволяют делать аналитику прямо в SQL, без подзапросов и группировок.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
🤔 Зачем нужен 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
👍5
🤔 Как объявлять слайс?

1. С помощью литералов: slice := []int{1, 2, 3}.
2. Через make: slice := make([]int, length, capacity), где length — длина, а capacity — ёмкость.
3. Пустой слайс: var slice []int.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Forwarded from easyoffer
Ура, друзья! Изиоффер переходит в публичное бета-тестирование!

🎉 Что нового:
🟢Анализ IT собеседований на основе 4500+ реальных интервью
🟢Вопросы из собеседований с вероятностью встречи
🟢Видео-примеры ответов на вопросы от Senior, Middle, Junior грейдов
🟢Пример лучшего ответа
🟢Задачи из собеседований
🟢Тестовые задания
🟢Примеры собеседований
🟢Фильтрация всего контента по грейдам, компаниям
🟢Тренажер подготовки к собеседованию на основе интервальных повторений и флеш карточек
🟡Тренажер "Реальное собеседование" с сценарием вопросов из реальных собеседований (скоро)
🟢Автоотклики на HeadHunter
🟢Закрытое сообщество easyoffer


💎 Акция в честь открытия для первых 500 покупателей:
🚀 Скидка 50% на PRO тариф на 1 год (15000₽ → 7500₽)

🔥 Акция уже стартовала! 👉 https://easyoffer.ru/pro
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Можно ли изменить определенный символ в строке?

Нет, строки (string) в Go неизменяемы (immutable). Это значит, что нельзя просто изменить один символ в строке.

🚩Почему нельзя изменить символ?

Строка в Go — это байтовый срез ([]byte), но неизменяемый. Когда вы создаёте строку
s := "hello"


Ошибка при попытке изменения символа напрямую
s := "hello"
s[0] = 'H' // Ошибка: cannot assign to s[0]


🚩Как изменить символ в строке?

Поскольку строка неизменяема, вам нужно создать новую строку с заменённым символом.
Способ 1: Преобразовать в []byte (для ASCII-строк)
Если строка содержит только английские буквы и символы ASCII, её можно преобразовать в []byte, заменить символ и создать новую строку.
package main

import "fmt"

func main() {
s := "hello"
b := []byte(s) // Преобразуем в изменяемый []byte
b[0] = 'H' // Меняем первый символ
s = string(b) // Преобразуем обратно в строку

fmt.Println(s) // "Hello"
}


Способ 2: Преобразовать в []rune (для Unicode)
Если строка содержит русские буквы, эмодзи или другие многобайтовые символы, используйте []rune.
package main

import "fmt"

func main() {
s := "привет"
r := []rune(s) // Преобразуем в []rune (массив символов)
r[0] = 'П' // Меняем первый символ
s = string(r) // Преобразуем обратно в строку

fmt.Println(s) // "Привет"
}


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

rune — это псевдоним для int32, который представляет один символ Unicode. Используется для работы с многоязычными текстами и символами, особенно когда требуется обработка не-ASCII символов. Это полезно в случаях, когда нужно обрабатывать строки на уровне символов, а не байтов.

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

Горутины и потоки (треды) в традиционном понимании операционных систем — это две различные концепции параллельного выполнения кода, каждая из которых имеет свои особенности и преимущества. Вот ключевые различия между ними.

🚩Модель управления

Горутины — это легковесные "зеленые" потоки, управляемые Go runtime. Они не являются потоками операционной системы, и Go runtime отвечает за их планирование и выполнение на доступных физических потоках. Это позволяет создавать тысячи и даже миллионы горутин в рамках одного приложения с относительно небольшими затратами памяти и CPU.
Треды — это потоки выполнения, управляемые непосредственно операционной системой. Каждый тред занимает значительно больше ресурсов, чем горутина, особенно в плане памяти и времени на создание и управление. Треды более подходят для задач, требующих высокой вычислительной мощности и прямого взаимодействия с операционной системой.

🚩Затраты ресурсов

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

🚩Масштабируемость

Горутины могут масштабироваться до большого количества параллельных задач благодаря меньшим требованиям к ресурсам и управлению со стороны runtime Go.
Треды ограничены в масштабируемости физическими ресурсами системы и более высокими затратами на управление.

🚩Контекст переключения

Горутины имеют намного более эффективный контекст переключения, так как Go runtime оптимизирован для работы с большим количеством горутин и их переключением.
Треды терпят большие затраты времени на переключение контекста, так как операционной системе требуется больше времени для управления потоками.
package main

import (
"fmt"
"time"
)

func say(text string) {
for i := 0; i < 5; i++ {
fmt.Println(text)
time.Sleep(time.Millisecond * 500)
}
}

func main() {
go say("Hello")
say("World")
}


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