Golang | Вопросы собесов
4.42K subscribers
38 photos
753 links
Download Telegram
🤔 Что такое хеш-функция?

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

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
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
🤔 Как можно откопировать слайс?

Слайсы являются ссылочными типами, поэтому простое присваивание одного слайса другому создаст новую ссылку на тот же подлежащий массив. Если вы хотите создать копию слайса с независимым подлежащим массивом, можно использовать встроенную функцию copy или методы, такие как использование append.

🚩Способы копирования слайса

🟠Использование функции `copy`
Создает побайтовую копию элементов из одного слайса в другой.
package main

import "fmt"

func main() {
original := []int{1, 2, 3, 4, 5}

// Создаем новый слайс той же длины, что и оригинал
copySlice := make([]int, len(original))

// Копируем элементы из оригинального слайса в новый
copy(copySlice, original)

// Изменяем элемент в копии
copySlice[0] = 100

fmt.Println("Оригинал:", original) // Выводит: Оригинал: [1 2 3 4 5]
fmt.Println("Копия:", copySlice) // Выводит: Копия: [100 2 3 4 5]
}


Использование функции
inal)   


Чтобы создать новый слайс с копированными элементами.
package main

import "fmt"

func main() {
original := []int{1, 2, 3, 4, 5}

// Копируем элементы из оригинального слайса в новый слайс
copySlice := append([]int(nil), original...)

// Изменяем элемент в копии
copySlice[0] = 100

fmt.Println("Оригинал:", original) // Выводит: Оригинал: [1 2 3 4 5]
fmt.Println("Копия:", copySlice) // Выводит: Копия: [100 2 3 4 5]
}


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

Тестировать распределённую систему можно через симуляцию нагрузки с помощью инструментов вроде Apache JMeter или Locust, проверку устойчивости к отказам (chaos engineering), и мониторинг метрик в реальном времени.


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

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

🚩Основные типы

🟠Статический NAT (Static NAT):
Фиксированный сопоставление: Один внутренний IP-адрес сопоставляется с одним внешним IP-адресом. Используется, когда необходимо, чтобы устройство в локальной сети всегда было доступно под одним и тем же публичным IP-адресом. Например Веб-сервер, который должен быть доступен из интернета под фиксированным IP-адресом.

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

🟠Преобразование адресов и портов (PAT, Port Address Translation), также известный как Маскарадинг (Masquerading):
Несколько внутренних IP-адресов могут использовать один внешний IP-адрес, но различаются по номерам портов. Каждый внутренний IP-адрес и порт сопоставляется с уникальным внешним портом. Например, Домашние или офисные сети, где множество устройств выходят в интернет через один публичный IP-адрес.

🚩Зачем нужен

🟠Сохранение IP-адресов:
IPv4-адресов недостаточно для всех устройств, и NAT позволяет использовать один публичный IP-адрес для множества устройств.

🟠Безопасность:
Внутренние IP-адреса не видны извне, что усложняет потенциальным злоумышленникам попытки атак на внутренние устройства.

🟠Управление подключениями:
NAT позволяет администрировать и контролировать сетевой трафик, предоставляя возможности для управления доступом и приоритизацией трафика.

🚩Принцип работы

🟠Инициирование соединения:
Когда устройство в локальной сети (например, компьютер с IP-адресом 192.168.1.10) инициирует соединение с устройством в интернете, NAT изменяет исходящий IP-адрес и порт на внешний IP-адрес маршрутизатора и уникальный номер порта.

🟠Ответный трафик:
Когда ответный пакет возвращается, NAT использует таблицу сопоставлений, чтобы определить, к какому внутреннему устройству направить пакет, и изменяет внешний IP-адрес и порт обратно на внутренний IP-адрес и порт.

🚩Пример работы PAT

1⃣Внутренний компьютер с IP-адресом 192.168.1.10 и портом 12345 инициирует соединение.
2⃣NAT изменяет это на внешний IP-адрес 203.0.113.1 и порт 54321.
3⃣Ответный пакет от сервера приходит на IP-адрес 203.0.113.1 и порт 54321.
4⃣NAT преобразует это обратно в 192.168.1.10:12345 и отправляет пакет внутреннему компьютеру.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
🤔 Что известно о lock-free концепции?

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

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

Объектно-ориентированное программирование (ООП) в Go и C# реализовано с использованием различных подходов и парадигм, отражающих философию и дизайн каждого языка.

🚩Go

🟠Классы и объекты
Используются структуры (struct).
type Person struct {
Name string
Age int
}

func (p *Person) Greet() {
fmt.Printf("Hello, my name is %s\n", p.Name)
}


🟠Наследование
Используется композиция вместо наследования.
type Employee struct {
Person
Position string
}


🟠Инкапсуляция
Модификаторы доступа на уровне пакета (экспортируемые и неэкспортируемые поля).
type Person struct {
name string // неэкспортируемое поле
Age int // экспортируемое поле
}


🟠Полиморфизм
Реализуется через интерфейсы.
type Greeter interface {
Greet()
}

type Person struct {
Name string
}

func (p *Person) Greet() {
fmt.Printf("Hello, my name is %s\n", p.Name)
}


🚩C#

🟠Классы и объекты
Используются классы.
public class Person {
public string Name { get; set; }
public int Age { get; set; }

public void Greet() {
Console.WriteLine($"Hello, my name is {Name}");
}
}


🟠Наследование
Поддерживается классическое наследование.
public class Employee : Person {
public string Position { get; set; }
}


🟠Инкапсуляция
Модификаторы доступа (public, private, protected).
public class Person {
private string name;
public int Age { get; set; }
}


🟠Полиморфизм
Через виртуальные методы и интерфейсы.
public class Person {
public virtual void Greet() {
Console.WriteLine("Hello!");
}
}

public class Employee : Person {
public override void Greet() {
Console.WriteLine("Hello, I am an employee!");
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
🤔 Как можно описать принцип работы lock-free?

Алгоритмы используют атомарные операции для проверки и обновления данных, повторяя попытки до успеха. Это предотвращает дедлоки и обеспечивает высокую производительность при параллельном доступе.

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