Golang | Вопросы собесов
4.54K subscribers
30 photos
853 links
Download Telegram
🤔 Что будет происходить при конкурентной записи в map?

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

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

HAVING — это оператор в SQL, который фильтрует группированные (GROUP BY) данные по агрегатным функциям (SUM, COUNT, AVG, MAX, MIN).

🚩Чем отличается `HAVING` от `WHERE`?

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?

Тип 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
🤔 Как избежать deadlock?

- Фиксировать транзакции быстрее – минимизировать время блокировки.
- Обращаться к таблицам в одном порядке во всех транзакциях.
- Использовать LOCK TABLES осторожно – избегать чрезмерного блокирования.
- Рассмотреть уровень изоляции – READ COMMITTED или REPEATABLE READ могут уменьшить вероятность дедлоков.
- Анализировать логи и SHOW ENGINE INNODB STATUS для выявления конфликтов.


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

HAVING — это оператор SQL, который фильтрует результаты после GROUP BY, аналогично WHERE, но работает с агрегатными функциями (COUNT(), SUM(), AVG(), MAX(), MIN()).

🚩Ключевая разница

WHERE фильтрует до GROUP BY (по отдельным строкам).
HAVING фильтрует после GROUP BY (по сгруппированным данным).

Пример 1: Фильтрация по HAVING
Задача: Вывести товары, у которых продано более 10 единиц.
SELECT product, SUM(quantity) as total_sold
FROM sales
GROUP BY product
HAVING SUM(quantity) > 10;


Пример 2: Разница между WHERE и HAVING
SELECT category, COUNT(*) as total_products
FROM products
WHERE price > 100 -- Убирает дешёвые товары ДО группировки
GROUP BY category
HAVING COUNT(*) > 5; -- Оставляет только категории с более 5 товаров


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

В Go есть два способа объявления переменной:
1. Быстрое объявление (:=) — используется внутри функций, тип выводится автоматически:
2. name := "Alice"
3. Объявление через var — даёт больше контроля, можно использовать вне функции и указывать тип:
4. var age int = 30
5. var city string
Краткое объявление невозможно на уровне пакета и не подходит для заранее объявленных, но ещё не инициализированных переменных.


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

В контексте gRPC (Google Remote Procedure Call) unary и stream — это два разных типа взаимодействия между клиентом и сервером.

🚩Unary RPC (Обычный вызов)

🟠Unary (унарный) вызов
это стандартный запрос-ответ:
Клиент отправляет одно сообщение → сервер отвечает одним сообщением.
service UserService {
rpc GetUserInfo(UserRequest) returns (UserResponse);
}


Go-реализация Unary RPC
func (s *server) GetUserInfo(ctx context.Context, req *pb.UserRequest) (*pb.UserResponse, error) {
user := &pb.UserResponse{
Id: req.Id,
Name: "John Doe",
Email: "john@example.com",
}
return user, nil // Обычный ответ
}


🚩Streaming RPC (Потоковый вызов)

В streaming RPC передача данных идёт потоком. gRPC поддерживает три вида стримов:

🟠Server Streaming (Поток от сервера)
Клиент отправляет один запрос → сервер возвращает поток ответов.
service UserService {
rpc GetUserActivity(UserRequest) returns (stream ActivityResponse);
}


Go-реализация Server Streaming
func (s *server) GetUserActivity(req *pb.UserRequest, stream pb.UserService_GetUserActivityServer) error {
activities := []string{"Login", "Upload File", "Logout"}
for _, activity := range activities {
err := stream.Send(&pb.ActivityResponse{Message: activity})
if err != nil {
return err
}
time.Sleep(time.Second) // Имитация задержки
}
return nil
}


🟠Client Streaming (Поток от клиента)
Клиент отправляет поток данных → сервер отвечает одним ответом.
service UploadService {
rpc UploadFile(stream FileChunk) returns (UploadResponse);
}


Go-реализация Client Streaming
func (s *server) UploadFile(stream pb.UploadService_UploadFileServer) error {
var totalSize int64
for {
chunk, err := stream.Recv()
if err == io.EOF {
return stream.SendAndClose(&pb.UploadResponse{Size: totalSize})
}
if err != nil {
return err
}
totalSize += chunk.Size
}
}


🟠Bidirectional Streaming (Двунаправленный поток)
Клиент и сервер обмениваются данными в потоке одновременно.
service ChatService {
rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}


Go-реализация Bi-directional Streaming
func (s *server) Chat(stream pb.ChatService_ChatServer) error {
for {
msg, err := stream.Recv()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
response := &pb.ChatMessage{Text: "Echo: " + msg.Text}
if err := stream.Send(response); err != nil {
return err
}
}
}


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

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


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

В Go, проверка типа интерфейса может быть выполнена несколькими способами: с помощью утверждения типа (type assertion) и с помощью конструкции switch для выбора типа.

🚩Утверждение типа (Type Assertion)

Утверждение типа позволяет проверить, является ли значение определенного интерфейса конкретным типом. Если да, то оно преобразует интерфейс в этот тип.
value, ok := interfaceValue.(ConcreteType)


🟠value
Значение типа ConcreteType, если утверждение типа успешно.
🟠ok
Булевое значение, указывающее, удалось ли преобразование.

package main

import "fmt"

func main() {
var i interface{} = "hello"

// Утверждение типа
s, ok := i.(string)
if ok {
fmt.Println("String:", s)
} else {
fmt.Println("Not a string")
}

// Утверждение типа, которое вызовет панику, если тип не соответствует
// Uncomment the line below to see the panic
// s := i.(string)
// fmt.Println(s)
}


🚩Использование `switch` для выбора типа

Конструкция switch позволяет проверить значение интерфейса на соответствие нескольким возможным типам.
switch v := interfaceValue.(type) {
case ConcreteType1:
// v имеет тип ConcreteType1
case ConcreteType2:
// v имеет тип ConcreteType2
default:
// v имеет другой тип
}


package main

import "fmt"

func printType(i interface{}) {
switch v := i.(type) {
case string:
fmt.Println("String:", v)
case int:
fmt.Println("Integer:", v)
case bool:
fmt.Println("Boolean:", v)
default:
fmt.Printf("Unknown type: %T\n", v)
}
}

func main() {
printType("hello")
printType(42)
printType(true)
printType(3.14)
}


Пример использования для проверки и работы с интерфейсами
package main

import (
"fmt"
)

type Person struct {
Name string
Age int
}

// Реализация интерфейса fmt.Stringer для типа Person
func (p Person) String() string {
return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func printValue(i interface{}) {
if str, ok := i.(fmt.Stringer); ok {
fmt.Println("Stringer:", str.String())
} else {
fmt.Println("Not a Stringer")
}
}

func main() {
p := Person{Name: "Alice", Age: 30}
printValue(p) // Проверка типа fmt.Stringer
printValue("Hello, world!") // Строка не реализует fmt.Stringer
}


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

int(string) невозможно, так как это несопоставимые типы, но можно конвертировать строку в число через strconv.Atoi. string(int) возможно, но результатом будет символ, соответствующий числовому значению в таблице Unicode.

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