Golang | Вопросы собесов
4.55K subscribers
28 photos
2 videos
809 links
Download Telegram
🤔 Как можно добавить элементы в слайс?

Используйте функцию append:
1. Добавление одного элемента: slice = append(slice, element).
2. Добавление нескольких элементов: slice = append(slice, elements...).
3. Слияние с другим слайсом: slice = append(slice, otherSlice...).


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

В Go для проверки работы горутины часто используют каналы. Они позволяют передавать данные между горутинами и могут использоваться для сигнализации о состоянии выполнения горутины.

🚩Основные способы проверки работы горутины через каналы

🟠Односторонний канал для завершения горутины
Горутина может отправлять сигнал (например, true) в канал, чтобы уведомить о своем завершении.
func worker(done chan bool) {
fmt.Println("Работа началась...")
time.Sleep(2 * time.Second) // Имитация работы
fmt.Println("Работа завершена!")
done <- true // Отправляем сигнал в канал
}

func main() {
done := make(chan bool)

go worker(done) // Запускаем горутину

// Ожидаем сигнал завершения
<-done
fmt.Println("Основной поток: горутина завершена")
}


🟠Канал для передачи промежуточных результатов
Горутина может отправлять данные в канал, чтобы сигнализировать о прогрессе выполнения.
func worker(progress chan int) {
for i := 1; i <= 5; i++ {
fmt.Printf("Шаг %d выполнен\n", i)
progress <- i // Отправляем номер шага в канал
time.Sleep(500 * time.Millisecond) // Имитация работы
}
close(progress) // Закрываем канал после завершения работы
}

func main() {
progress := make(chan int)

go worker(progress) // Запускаем горутину

// Считываем данные из канала
for step := range progress {
fmt.Printf("Получен сигнал: шаг %d завершен\n", step)
}
fmt.Println("Все шаги выполнены!")
}


🟠Тайм-ауты и проверка работы через `select`
Если важно знать, работает ли горутина, но при этом нужно ограничить ожидание, используется оператор select с тайм-аутом.
func worker(status chan string) {
time.Sleep(2 * time.Second) // Имитация работы
status <- "Горутина завершена"
}

func main() {
status := make(chan string)

go worker(status)

select {
case msg := <-status:
fmt.Println(msg)
case <-time.After(1 * time.Second): // Тайм-аут 1 секунда
fmt.Println("Горутина работает слишком долго")
}
}


🟠Закрытие канала как индикатор завершения
Закрытие канала может служить сигналом того, что горутина завершила свою работу.
func worker(done chan struct{}) {
fmt.Println("Горутина работает...")
time.Sleep(2 * time.Second)
fmt.Println("Горутина завершена!")
close(done) // Закрываем канал
}

func main() {
done := make(chan struct{})

go worker(done)

// Проверяем, когда канал закроется
<-done
fmt.Println("Основной поток: горутина завершила работу")
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
🤔 Что такое хэш-таблица?

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

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

Оператор "квадратные скобки" ([]) при применении к строке используется для доступа к отдельным байтам в этой строке. Строки представлены как последовательности байтов, и оператор [] позволяет получить байт по указанному индексу.

package main

import (
"fmt"
)

func main() {
str := "hello"

// Получаем байт по индексу
firstByte := str[0]

// Выводим байт и его символ
fmt.Printf("Первый байт: %d\n", firstByte) // Выводит: 104
fmt.Printf("Первый символ: %c\n", firstByte) // Выводит: h
}


🚩Объяснение

1⃣Доступ к байту
В этой строке кода мы получаем байт, расположенный по индексу 0 в строке str. В данном случае это байт, соответствующий символу 'h'.
firstByte := str[0]   


2⃣Вывод байта в числовом формате
Здесь мы выводим байт в виде целого числа. Поскольку символ 'h' имеет ASCII-код 104, вывод будет 104.
fmt.Printf("Первый байт: %d\n", firstByte)   


3⃣Вывод байта как символа
Мы также можем вывести байт как символ, используя формат %c. Это отобразит символ 'h'.
fmt.Printf("Первый символ: %c\n", firstByte)   


🚩Работа с Unicode

Важно понимать, что строки являются последовательностями байтов, а не символов. Это означает, что доступ по индексу с помощью [] дает байт, а не руну (rune). Если строка содержит многобайтовые символы (например, символы Unicode), то доступ по индексу может вернуть только один из байтов, составляющих символ.
package main

import (
"fmt"
)

func main() {
str := "Привет"

// Получаем байт по индексу
firstByte := str[0]

// Выводим байт и его символ
fmt.Printf("Первый байт: %d\n", firstByte) // Выводит: 208
fmt.Printf("Первый символ: %c\n", firstByte) // Выводит: � (неполный символ)
}


Для корректной работы с многобайтовыми символами (рунами) в строках используется преобразование строки в срез рун
package main

import (
"fmt"
)

func main() {
str := "Привет"

// Преобразуем строку в срез рун
runes := []rune(str)

// Получаем руну по индексу
firstRune := runes[0]

// Выводим руну и её символ
fmt.Printf("Первая руна: %d\n", firstRune) // Выводит: 1055 (код Unicode для 'П')
fmt.Printf("Первый символ: %c\n", firstRune) // Выводит: П
}


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

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

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

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

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

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

🟠Объявление массива
С указанием типа элементов и фиксированного размера. Это объявление создает массив из пяти целых чисел, инициализированных нулями.
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]


🚩Сравнение

🟠Размер
Массивы имеют фиксированный размер, тогда как слайсы динамичны.

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

🟠Гибкость: Слайсы более гибки благодаря динамическому изменению размера и доступным методам.

Использование массивов
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
👍4
🤔 Что такое хеш-функция?

Это алгоритм, который преобразует входные данные произвольного размера в строку фиксированной длины (хеш). Её задача — равномерно распределять данные по возможным индексам, минимизируя коллизии. Важными характеристиками являются скорость вычисления и устойчивость к предсказанию результата.

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

Нельзя напрямую взять ссылку на значение, хранящееся по ключу в карте (map), из-за особенностей реализации карт и управления памятью. Рассмотрим подробнее, почему это так.

🚩Причины, почему нельзя брать ссылку на значение в карте

🟠Внутреннее устройство карты (map)
Карты реализованы на основе хеш-таблиц. Внутреннее устройство карты предполагает, что значения могут перемещаться в памяти при выполнении операций, таких как добавление или удаление элементов. Хеш-таблица может перераспределять (реорганизовывать) свои внутренние структуры для оптимизации доступа к элементам. Это может происходить, например, когда карта увеличивается в размере.

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

🚩Демонстрация проблемы

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

import "fmt"

func main() {
m := map[string]int{"a": 1, "b": 2}

// Нельзя делать так:
// p := &m["a"]

// Вместо этого можно работать с копией значения
value := m["a"]
p := &value

fmt.Println("Value:", *p) // 1

// Изменение карты
m["c"] = 3

// Ссылка на значение в карте могла бы стать недействительной
// fmt.Println("Value after map change:", *p)
}


🚩Правильные способы работы со значениями карты

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

🟠Работа с копией значения
Получить значение из карты и сохранить его в переменную.
value := m["a"]   


🟠Изменение значения в карте
Если необходимо изменить значение в карте, его нужно сначала извлечь, изменить, а затем снова записать в карту.
value := m["a"]
value = value + 10
m["a"] = value


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

import "fmt"

func main() {
m := map[string]*int{"a": new(int), "b": new(int)}
*m["a"] = 1
*m["b"] = 2

// Теперь можно брать указатели на значения
p := m["a"]
fmt.Println("Value:", *p) // 1

// Изменение значения через указатель
*p = 42
fmt.Println("Updated Value:", *m["a"]) // 42
}


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

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


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

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

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

🟠Компиляция и скорость
Go — компилируемый язык, обеспечивающий высокую производительность.
🟠Простота
Язык избегает избыточности, улучшая читаемость кода.
🟠Сборка мусора
Автоматическое управление памятью.
🟠Конкурентность
Встроенные средства для работы с параллельными вычислениями, такие как горутины и каналы.
🟠Стандартная библиотека
Широкий набор инструментов и библиотек.

🚩Пример простого приложения

Простого веб-сервера:
package main

import (
"fmt"
"net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}

func main() {
http.HandleFunc("/", helloHandler)
fmt.Println("Starting server on :8080")
http.ListenAndServe(":8080", nil)
}


🚩Основные концепции

🟠Горутины
Легковесные потоки для параллельных вычислений.
go func() {
fmt.Println("Hello from a goroutine!")
}()


🟠Каналы
Средства обмена данными между горутинами.
ch := make(chan int)
go func() {
ch <- 42
}()
value := <-ch
fmt.Println(value)


🟠Интерфейсы
Абстракция поведения без привязки к реализации.
type Stringer interface {
String() string
}


🟠Пакеты
Организация кода для управления и повторного использования.
package mypackage

import "fmt"

func MyFunction() {
fmt.Println("Hello from mypackage")
}


🚩Применение Go

Go используется для серверного ПО, облачных сервисов, микросервисов, инструментов командной строки и систем с высокой производительностью. Известные проекты на Go включают Kubernetes, Docker, Prometheus, а также Google, Dropbox и Netflix.

🚩Плюсы и минусы

Высокая производительность
Быстро компилируемый язык.
Простота и читаемость
Минимум синтаксического шума.
Конкурентность
Простые механизмы параллельных вычислений.
Богатая библиотека
Широкий набор встроенных инструментов.
Ограниченные обобщения
Ранее отсутствовали, добавлены в Go 1.18.
Нет исключений
Используется управление ошибками через возвращаемые значения.

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

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


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

Плюсы: масштабируемость, гибкость в разработке и развертывании, изоляция ошибок.
Минусы: сложность разработки, взаимодействия сервисов, управление данными и отладка.


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

Это неизменяемые последовательности байтов, обычно представляющие текст в кодировке UTF-8. Работа с ними в Go основывается на использовании встроенных функций, методов стандартной библиотеки и специальных типов данных.

🟠Конкатенация строк
Самый простой способ объединить строки — использовать оператор + или функцию fmt.Sprintf.
package main

import "fmt"

func main() {
s1 := "Привет"
s2 := "Мир"
result := s1 + ", " + s2 + "!"
fmt.Println(result) // Привет, Мир!

// Через fmt.Sprintf
formatted := fmt.Sprintf("%s, %s!", s1, s2)
fmt.Println(formatted) // Привет, Мир!
}


🟠Получение длины строки
Функция len возвращает длину строки в байтах, а не в символах.
package main

import "fmt"

func main() {
str := "Привет"
fmt.Println(len(str)) // 12, так как кириллические символы занимают 2 байта
}


🟠Итерация по строке
Строки можно обойти как в виде байтов, так и в виде рун (Unicode символов).
package main

import (
"fmt"
"unicode/utf8"
)

func main() {
str := "Привет"

// Итерация по байтам
for i := 0; i < len(str); i++ {
fmt.Printf("Байт: %x\n", str[i])
}

// Итерация по символам (рунам)
for _, runeValue := range str {
fmt.Printf("Символ: %c\n", runeValue)
}

// Количество рун
fmt.Println("Количество символов:", utf8.RuneCountInString(str))
}


🟠Извлечение подстроки
Так как строки неизменяемы, для извлечения подстроки используется срез (slice).
package main

import "fmt"

func main() {
str := "Привет, Мир!"
substring := str[8:] // С 8-го байта до конца
fmt.Println(substring) // Мир!
}


🟠Разделение и объединение строк
Функции strings.Split и strings.Join из пакета strings позволяют разбивать строку на части или объединять части в строку.
package main

import (
"fmt"
"strings"
)

func main() {
str := "apple,banana,cherry"

// Разделение строки
parts := strings.Split(str, ",")
fmt.Println(parts) // [apple banana cherry]

// Объединение строк
joined := strings.Join(parts, " | ")
fmt.Println(joined) // apple | banana | cherry
}


🟠Поиск и замена подстроки
Для поиска подстроки можно использовать strings.Contains, strings.Index или strings.HasPrefix/strings.HasSuffix. Для замены — strings.Replace.
package main

import (
"fmt"
"strings"
)

func main() {
str := "Go — это круто!"

// Поиск подстроки
fmt.Println(strings.Contains(str, "круто")) // true
fmt.Println(strings.Index(str, "это")) // 4

// Замена подстроки
newStr := strings.Replace(str, "круто", "отлично", 1)
fmt.Println(newStr) // Go — это отлично!
}


🟠Преобразование регистра
Стандартная библиотека предоставляет функции для изменения регистра строки: strings.ToLower и strings.ToUpper.
package main

import (
"fmt"
"strings"
)

func main() {
str := "Hello, Go!"
fmt.Println(strings.ToUpper(str)) // HELLO, GO!
fmt.Println(strings.ToLower(str)) // hello, go!
}


🟠Тримминг строки
Удаление пробелов или других символов с начала/конца строки выполняется с помощью strings.Trim, strings.TrimSpace и других функций.
package main

import (
"fmt"
"strings"
)

func main() {
str := " Hello, Go! "
fmt.Println(strings.TrimSpace(str)) // "Hello, Go!"
}


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

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

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

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

🚩Процесс

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

🚩Поток (Thread)

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

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

🟠Изоляция
Процессы изолированы друг от друга, в то время как потоки делят состояние и ресурсы внутри одного процесса.

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

🟠Создание и управление
Создание нового процесса более ресурсоемко, чем создание потока внутри существующего процесса.

🟠Взаимодействие
Взаимодействие между процессами требует использования межпроцессного взаимодействия (IPC), такого как сокеты, разделяемая память, очереди сообщений и т. д. Потоки внутри процесса могут общаться друг с другом напрямую через общую память.

🟠Надежность и безопасность
Ошибка в одном процессе обычно не влияет на другие процессы, но ошибка в одном потоке может привести к сбою всего процесса.

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

Это современное развитие SSL, обеспечивающее более безопасную и эффективную передачу данных, включая шифрование, проверку подлинности и защиту от подмены данных.

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

Это целочисленные значения, которые используются для доступа к элементам упорядоченных структур данных. В контексте 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
3👍1🎉1
🤔 Есть отличия между SSL и TLS?

Да, TLS безопаснее и быстрее, поддерживает более современные криптографические алгоритмы и протоколы, в отличие от устаревшего SSL, который более подвержен уязвимостям.


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

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

🚩Использование каналов для управления горутинами

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

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

func worker(stopCh <-chan struct{}, wg *sync.WaitGroup, id int) {
defer wg.Done()
for {
select {
case <-stopCh:
fmt.Printf("Worker %d stopping\n", id)
return
default:
// выполнение полезной работы
fmt.Printf("Worker %d working\n", id)
time.Sleep(time.Second)
}
}
}

func main() {
var wg sync.WaitGroup
stopCh := make(chan struct{})

// запуск горутин
for i := 0; i < 3; i++ {
wg.Add(1)
go worker(stopCh, &wg, i)
}

// остановка горутин после 3 секунд
time.Sleep(3 * time.Second)
close(stopCh) // отправка сигнала всем горутинам остановиться
wg.Wait() // ожидание завершения всех горутин
}


🟠Использование пакета context

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

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

func worker(ctx context.Context, wg *sync.WaitGroup, id int) {
defer wg.Done()
for {
select {
case <-ctx.Done():
fmt.Printf("Worker %d stopping\n", id)
return
default:
// выполнение полезной работы
fmt.Printf("Worker %d working\n", id)
time.Sleep(time.Second)
}
}
}

func main() {
var wg sync.WaitGroup
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)

// запуск горутин
for i := 0; i < 3; i++ {
wg.Add(1)
go worker(ctx, &wg, i)
}

wg.Wait() // ожидание завершения всех горутин
cancel() // убедиться, что все ресурсы освобождены
}


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

Можно использовать встроенную функцию reflect.TypeOf() из пакета reflect для определения типа переменной.

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