Golang | Вопросы собесов
4.33K subscribers
28 photos
694 links
Download 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
🤔 Что такое репликация?

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

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

ACID — это набор свойств транзакций в базах данных, обеспечивающий надежность и целостность данных.

🚩ACID

🟠A (Atomicity) — Атомарность
Транзакция выполняется либо полностью, либо не выполняется вовсе.
Пример: Если при переводе денег со счета A на счет B ошибка произошла на полпути, изменения откатываются.

🟠C (Consistency) — Согласованность
Данные остаются в правильном состоянии до и после транзакции.
Пример: Если сумма на всех счетах банка должна оставаться неизменной, транзакция не должна нарушить это правило.

🟠I (Isolation) — Изолированность
Одновременные транзакции не мешают друг другу.
Пример: Два клиента покупают один и тот же товар, но база данных правильно обрабатывает, кто купил первым.

🟠D (Durability) — Долговечность
После завершения транзакции изменения сохраняются, даже если система сломается.
Пример: Если заказ оформлен, он не исчезнет при внезапном отключении электричества.

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

Go использует трассирующий сборщик мусора с метками (mark-and-sweep).
Он проходит в два этапа:
1. Mark — находят все доступные (живые) объекты.
2. Sweep — освобождают недоступные (мертвые) объекты.
GC работает инкрементально и в параллель с приложением, начиная с Go 1.5.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Можно ли сделать int(string) и string(int) соответственно?

Существуют встроенные функции для преобразования типов, включая преобразование из строки в целое число и наоборот. Для этих целей используются функции из стандартной библиотеки strconv. Рассмотрим, как это делается.

🚩Преобразование строки в целое число

Для этого используется функция strconv.Atoi. Она возвращает два значения: само число и ошибку, если преобразование не удалось.
package main

import (
"fmt"
"strconv"
)

func main() {
str := "123"
num, err := strconv.Atoi(str)
if err != nil {
fmt.Println("Error converting string to int:", err)
} else {
fmt.Println("Converted number:", num)
}
}


🚩Преобразование целого числа в строку

Для этого используется функция strconv.Itoa.
package main

import (
"fmt"
"strconv"
)

func main() {
num := 123
str := strconv.Itoa(num)
fmt.Println("Converted string:", str)
}


🚩Обработка ошибок при преобразовании

Важно обрабатывать ошибки при преобразовании типов, особенно при преобразовании строки в целое число, чтобы избежать неожиданных сбоев в программе.
package main

import (
"fmt"
"strconv"
)

func main() {
str := "abc"
num, err := strconv.Atoi(str)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Converted number:", num)
}
}


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

Перед названием метода указывается ресивер — переменная, к которой метод привязан. Он описывается в круглых скобках перед именем метода и указывает, для какого типа метод определён.
Здесь u *User — это ресивер. Он определяет, что метод PrintName относится к типу User, и при вызове будет доступ к его полям.


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

Размер числа в байтах зависит от его типа данных. В Go есть несколько числовых типов, и каждый занимает определённое количество байтов в памяти.

🚩Проверка размера в Go (`unsafe.Sizeof`)

Можно проверить размер типа с помощью unsafe.Sizeof()
package main

import (
"fmt"
"unsafe"
)

func main() {
var a int64
var b float64
var c byte // то же самое, что uint8
fmt.Println("int64:", unsafe.Sizeof(a)) // 8
fmt.Println("float64:", unsafe.Sizeof(b)) // 8
fmt.Println("byte:", unsafe.Sizeof(c)) // 1
}


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

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

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

Карты (maps) реализованы на основе хеш-таблиц, что обеспечивает быстрый доступ к значениям по ключам. Давайте рассмотрим, как происходит поиск по ключу в карте, и какие этапы включены в этот процесс.

🚩Основные этапы

🟠Хеширование ключа
Сначала вычисляется хеш-значение ключа. Функция хеширования преобразует ключ в целое число, которое служит индексом в хеш-таблице.

🟠Поиск в хеш-таблице
Хеш-значение используется для доступа к соответствующей "ячейке" или "корзине" (bucket) в хеш-таблице.

🟠Поиск в корзине
Если корзина содержит несколько элементов (из-за коллизий хеширования), Go выполняет линейный поиск среди этих элементов, сравнивая ключи с использованием оператора ==.

🚩Детали

🟠Хеширование ключа
Когда вы пытаетесь получить значение по ключу, Go сначала вычисляет хеш-значение этого ключа. Хеш-функция берет ключ (например, строку или целое число) и преобразует его в индекс хеш-таблицы.

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

🟠Линейный поиск внутри корзины
Если корзина содержит несколько элементов, Go выполняет линейный поиск среди этих элементов. Для каждого элемента в корзине сравнивается ключ с искомым ключом с использованием оператора ==. Если ключи совпадают, возвращается соответствующее значение. Если ключ не найден, возвращается нулевое значение типа (zero value) и флаг, указывающий на отсутствие ключа.

package main

import "fmt"

func main() {
myMap := map[string]int{
"Alice": 25,
"Bob": 30,
}

value, exists := myMap["Alice"]
if exists {
fmt.Println("Alice:", value) // Alice: 25
} else {
fmt.Println("Alice not found")
}

value, exists = myMap["Charlie"]
if exists {
fmt.Println("Charlie:", value)
} else {
fmt.Println("Charlie not found") // Charlie not found
}
}


🚩Подводные камни и особенности

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

🟠Производительность
В среднем, доступ к элементу в карте осуществляется за константное время O(1), что делает карты очень эффективными для поиска по ключу. Однако в худшем случае, при большой нагрузке коллизий, производительность может деградировать до линейного времени O(n).

🟠Изменение карты во время поиска
Карты не являются потокобезопасными. Если одна горутина изменяет карту, в то время как другая горутина читает из нее, это может привести к панике. Для обеспечения потокобезопасности используйте мьютексы или структуру sync.Map.

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

- Юнит-тесты проверяют отдельные функции или методы в изоляции от остального кода. Быстрые, лёгкие, часто запускаются.
- Интеграционные тесты проверяют взаимодействие между компонентами, например, работу сервиса с базой или API с внешней системой.
Юнит-тесты дают быструю обратную связь, интеграционные — показывают, как работает система целиком.


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