Golang | Вопросы собесов
4.34K subscribers
27 photos
2 videos
707 links
Download Telegram
Что такое NAT ?
Спросят с вероятностью 8%

NAT (Network Address Translation, трансляция сетевых адресов) — это технология, используемая для изменения сетевых адресов в IP-пакетах при их прохождении через маршрутизатор или межсетевой экран. Позволяет нескольким устройствам в локальной сети (LAN) использовать один публичный IP-адрес для выхода.

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

1️⃣SNAT (Source Network Address Translation):
Используется для изменения исходного IP-адреса в пакете при его отправке из локальной сети в Интернет.
Пример: все устройства в локальной сети используют один публичный IP-адрес для доступа в Интернет.

2️⃣DNAT (Destination Network Address Translation):
Используется для изменения IP-адреса назначения в пакете при его получении извне.
Пример: перенаправление входящих запросов на конкретный сервер в локальной сети.

3️⃣PAT (Port Address Translation, также известный как NAT Overload):
Специфический тип SNAT, который позволяет использовать один публичный IP-адрес для множества устройств, различая их по номерам портов.
Пример: различные устройства в локальной сети могут одновременно устанавливать соединения через один публичный IP-адрес, используя разные порты.

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

1️⃣Исходящий трафик (SNAT/PAT):
Когда устройство в локальной сети отправляет пакет, маршрутизатор с NAT заменяет его внутренний IP-адрес на публичный IP-адрес маршрутизатора.
При необходимости, также заменяет номер порта отправителя.
Маршрутизатор сохраняет соответствие между внутренним IP-адресом и портом и публичным IP-адресом и портом в таблице.

2️⃣Входящий трафик (DNAT/PAT):
Когда маршрутизатор получает ответный пакет из Интернета, он использует таблицу NAT для преобразования публичного IP-адреса и порта обратно во внутренний IP-адрес и порт.
Пакет передается на соответствующее устройство в локальной сети.

Пример:

Исходящее соединение


1️⃣Устройство с IP-адресом 192.168.1.10 и портом 12345 отправляет запрос на сервер в Интернете с IP-адресом 8.8.8.8 и портом 80.
2️⃣Маршрутизатор с NAT заменяет исходный IP-адрес 192.168.1.10 на публичный IP-адрес, например, 203.0.113.1, и номер порта 12345 на другой доступный порт, например, 54321.
3️⃣Сервер в Интернете получает запрос от 203.0.113.1:54321 и отправляет ответ на этот же адрес и порт.
4️⃣Маршрутизатор получает ответ и использует таблицу NAT для замены 203.0.113.1:54321 обратно на 192.168.1.10:12345.
5️⃣Устройство 192.168.1.10 получает ответ от сервера.

Входящее соединение (перенаправление портов)

1️⃣Внешний клиент пытается соединиться с публичным IP-адресом 203.0.113.1 на порту 8080.
2️⃣Маршрутизатор с DNAT перенаправляет этот запрос на внутренний IP-адрес 192.168.1.20 на порт 80.
3️⃣Внутренний сервер с IP-адресом 192.168.1.20 на порту 80 получает запрос и обрабатывает его.

Преимущества

1️⃣Экономия IP-адресов:
Позволяет использовать один публичный IP-адрес для множества устройств в локальной сети.

2️⃣Улучшение безопасности:
Скрывает внутренние IP-адреса от внешних сетей, что затрудняет несанкционированный доступ.

3️⃣Гибкость в сетевой конфигурации:
Позволяет легко изменять внутренние сетевые адреса без необходимости изменения внешних настроек.

Недостатки

1️⃣Задержки:
Процесс трансляции адресов может добавить небольшие задержки в передачу пакетов.

2️⃣Совместимость приложений:
Некоторые приложения, особенно те, которые используют встроенные IP-адреса или специфические протоколы (например, SIP, FTP), могут испытывать проблемы с NAT.

3️⃣Усложнение сетевых настроек:
Администрирование и отладка сетевых проблем может быть сложнее из-за трансляции адресов.

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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Как полиморфизм осуществлен в Golang ?
Спросят с вероятностью 17%

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

Интерфейсы


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

Давайте рассмотрим простой пример, демонстрирующий, как полиморфизм может быть реализован в Go с помощью интерфейсов:
package main

import "fmt"

// Shape интерфейс, определяющий метод Area
type Shape interface {
Area() float64
}

// Circle структура, представляющая круг
type Circle struct {
Radius float64
}

// Area метод для Circle
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}

// Rectangle структура, представляющая прямоугольник
type Rectangle struct {
Width, Height float64
}

// Area метод для Rectangle
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}

// TotalArea функция, принимающая слайс фигур и возвращающая суммарную площадь
func TotalArea(shapes []Shape) float64 {
var total float64
for _, s := range shapes {
total += s.Area()
}
return total
}

func main() {
circle := Circle{Radius: 5}
rectangle := Rectangle{Width: 3, Height: 4}

shapes := []Shape{circle, rectangle}
fmt.Println("Total Area:", TotalArea(shapes))
}


В этом примере:
Интерфейс Shape определяет метод Area().
Circle и Rectangle оба реализуют этот интерфейс.
Функция TotalArea принимает слайс объектов, которые реализуют интерфейс Shape. Это позволяет функции работать с любыми объектами, которые удовлетворяют интерфейсу Shape, что и является демонстрацией полиморфизма: одна функция обрабатывает различные типы данных.

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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Какой механизм в Go используется для обработки ошибок?
Anonymous Quiz
11%
Exceptions
9%
Try/catch
70%
Error interface
10%
Event handlers
Как произвести дебаг protobuff ?
Спросят с вероятностью 8%

Дебаггинг Protocol Buffers (protobuf) может быть сложной задачей, поскольку он включает работу с бинарными форматами данных и сериализацией. Однако существуют инструменты и методы, которые помогут вам отлаживать и анализировать данные в protobuf.

Шаги:

1️⃣Проверка схемы .proto


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

Пример:
syntax = "proto3";

message Person {
string name = 1;
int32 id = 2;
string email = 3;
}


2️⃣Генерация кодов из схемы .proto

Убедитесь, что вы правильно сгенерировали код для вашей схемы. Используйте соответствующий компилятор protobuf для вашего языка программирования.
protoc --go_out=. --go_opt=paths=source_relative yourfile.proto


3️⃣Логирование и печать сообщений

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

import (
"fmt"
"log"

"google.golang.org/protobuf/proto"
pb "path/to/your/protobuf/generated/code"
)

func main() {
// Создание сообщения
person := &pb.Person{
Name: "Alice",
Id: 1234,
Email: "alice@example.com",
}

// Сериализация сообщения в бинарный формат
data, err := proto.Marshal(person)
if err != nil {
log.Fatal("Marshaling error: ", err)
}

// Десериализация сообщения из бинарного формата
newPerson := &pb.Person{}
err = proto.Unmarshal(data, newPerson)
if err != nil {
log.Fatal("Unmarshaling error: ", err)
}

// Печать сообщения в текстовом формате
fmt.Println("Original person: ", person)
fmt.Println("Deserialized person: ", newPerson)
}


4️⃣Использование текстового формата protobuf

Можно использовать текстовый формат protobuf для логирования и отладки. Текстовый формат легче читать и анализировать по сравнению с бинарным форматом.
import (
"google.golang.org/protobuf/encoding/prototext"
)

func main() {
// Печать сообщения в текстовом формате
fmt.Println("Original person (text): ", prototext.Format(person))
}


5️⃣Инструменты для анализа protobuf

Существует несколько инструментов, которые могут помочь вам анализировать и отлаживать сообщения protobuf.

Команда protoc поддерживает преобразование бинарных данных в текстовый формат и обратно.

Сериализация сообщения в бинарный файл:
echo 'name: "Alice" id: 1234 email: "alice@example.com"' | protoc --encode=Person yourfile.proto > person.bin


Десериализация сообщения из бинарного файла:
protoc --decode=Person yourfile.proto < person.bin


6️⃣Проверка версии библиотеки protobuf

Убедитесь, что у вас установлена правильная версия библиотеки protobuf, соответствующая версии протокола, которую вы используете. Неверная версия библиотеки может привести к проблемам с сериализацией и десериализацией.

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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Что произойдет, если канал в Go заполнен и на него пытаются отправить данные?
Anonymous Quiz
4%
Данные заменят старые
60%
Горутина заблокируется
7%
Канал расширится
29%
Возникнет паника
Какие бывают типы в Go ?
Спросят с вероятностью 17%

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

Базовые типы

1️⃣Числовые типы
Целые числа:
int (размер зависит от платформы):int8, int16, int32, int64 ; uint (беззнаковый, размер зависит от платформы) ; uint8 (также известен как byte), uint16, uint32, uint64
Числа с плавающей запятой:float32, float64
Комплексные числа:complex64, complex128

2️⃣Булевый тип
bool (значения true и false)

3️⃣Символьные типы
byte (аналог uint8)
rune (аналог int32, используется для представления символов Unicode)

4️⃣Строки
string (последовательность байт, используемая для хранения текста)

Агрегированные типы

1️⃣Массивы
Фиксированный размер: [n]T (например, [5]int для массива из пяти целых чисел)

2️⃣Срезы
Переменный размер: []T (например, []int для среза целых чисел)

3️⃣Структуры
Набор полей: struct (например, type Person struct { Name string; Age int })

Ссылочные типы

1️⃣Указатели
Хранит адрес переменной: *T (например, *int для указателя на целое число)

2️⃣Карты (map)
Хранит пары ключ-значение: map[K]V (например, map[string]int для карты, где ключи - строки, а значения - целые числа)

3️⃣Функции
Определяет тип функции: func(параметры) возвращаемые_типы (например, func(int) int для функции, принимающей целое число и возвращающей целое число)

4️⃣Интерфейсы
Определяет методы, которые должны быть реализованы: interface{} (например, type Stringer interface { String() string })

Рассмотрим небольшой пример, демонстрирующий использование различных типов:
package main

import "fmt"

// Определение структуры
type Person struct {
Name string
Age int
}

// Функция, использующая интерфейс
func (p Person) String() string {
return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func main() {
// Пример использования базовых типов
var age int = 30
var name string = "Alice"
var isStudent bool = false

// Пример использования агрегированных типов
var scores [3]int = [3]int{90, 85, 88}
var people []Person = []Person{
{Name: "Bob", Age: 25},
{Name: "Charlie", Age: 35},
}

// Пример использования ссылочных типов
var p *Person = &Person{Name: "Dave", Age: 40}
var ageMap map[string]int = map[string]int{"Alice": 30, "Bob": 25}

// Вывод данных
fmt.Println("Name:", name)
fmt.Println("Age:", age)
fmt.Println("Is student:", isStudent)
fmt.Println("Scores:", scores)
fmt.Println("People:", people)
fmt.Println("Pointer to Person:", p)
fmt.Println("Age map:", ageMap)
}


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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Как наследование осуществлено в Golang ?
Спросят с вероятностью 17%

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

Композиция

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

import "fmt"

// Определение структуры
type Engine struct {
Power int
}

func (e Engine) Start() {
fmt.Println("Engine started with power:", e.Power)
}

// Определение другой структуры, которая включает первую
type Car struct {
Brand string
Engine
}

func main() {
myCar := Car{
Brand: "Toyota",
Engine: Engine{Power: 150},
}

fmt.Println("Car brand:", myCar.Brand)
myCar.Start() // Вызов метода встроенной структуры
}


В данном примере структура Car включает в себя структуру Engine. Это позволяет вызывать метод Start напрямую через myCar, как если бы он был определен в Car.

Интерфейсы

Определяют набор методов, которые должны быть реализованы типом. Любой тип, реализующий все методы интерфейса, автоматически рассматривается как реализующий этот интерфейс. Это дает возможность полиморфизма.
package main

import "fmt"

// Определение интерфейса
type Drivable interface {
Drive()
}

// Определение структуры, реализующей интерфейс
type Car struct {
Brand string
}

func (c Car) Drive() {
fmt.Println(c.Brand, "is driving")
}

// Еще одна структура, реализующая интерфейс
type Bike struct {
Brand string
}

func (b Bike) Drive() {
fmt.Println(b.Brand, "is driving")
}

// Функция, принимающая интерфейс
func StartDriving(d Drivable) {
d.Drive()
}

func main() {
car := Car{Brand: "Toyota"}
bike := Bike{Brand: "Yamaha"}

StartDriving(car)
StartDriving(bike)
}


В этом примере структуры Car и Bike реализуют интерфейс Drivable, определяя метод Drive. Функция StartDriving принимает любой тип, который реализует интерфейс Drivable, что позволяет вызывать метод Drive для разных типов.

Встраивание интерфейсов

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

import "fmt"

// Определение базового интерфейса
type Printer interface {
Print()
}

// Определение другого интерфейса, включающего первый
type AdvancedPrinter interface {
Printer
Scan()
}

// Реализация структуры, реализующей расширенный интерфейс
type MultiFunctionPrinter struct{}

func (m MultiFunctionPrinter) Print() {
fmt.Println("Printing...")
}

func (m MultiFunctionPrinter) Scan() {
fmt.Println("Scanning...")
}

func main() {
mfp := MultiFunctionPrinter{}
mfp.Print()
mfp.Scan()
}


В данном примере AdvancedPrinter включает в себя интерфейс Printer, и структура MultiFunctionPrinter реализует оба метода, тем самым удовлетворяя оба интерфейса.

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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Что такое интерфейс в Go и как он отличается от других языков программирования?
Anonymous Quiz
16%
Явное наследование
57%
Неявное удовлетворение
18%
Специальные методы
10%
Дженерики
Что можешь сказать о HTTP3 ?
Спросят с вероятностью 8%

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

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

Использование QUIC вместо TCP


QUIC (Quick UDP Internet Connections) — это транспортный протокол, разработанный Google, который работает поверх UDP.
Сокращение времени установки соединения: Устраняет необходимость в нескольких обменах данными для установки соединения, что существенно сокращает задержки при установке нового соединения.
Улучшенная передача данных: Обеспечивает более эффективное управление потерей пакетов и повторной передачей данных, что улучшает производительность в условиях ненадежных сетей.
Встроенное шифрование: Все соединения зашифрованы по умолчанию, что повышает безопасность передачи данных.

Основные преимущества

1️⃣Скорость и производительность:
Быстрое установление соединения: за счет использования QUIC вместо TCP, HTTP/3 устраняет задержки, связанные с установкой соединения и шифрованием (TLS handshake).
Мультиплексирование: Позволяет отправлять несколько запросов и получать ответы одновременно по одному соединению без блокировки, что устраняет проблему "head-of-line blocking", присущую HTTP/2.

2️⃣Надежность:
Улучшенное управление потерей пакетов: Имеет встроенные механизмы для быстрого обнаружения и восстановления потерянных пакетов, что делает передачу данных более устойчивой.
Независимость от порядка доставки: Мультиплексирование потоков данных в QUIC означает, что потеря пакетов в одном потоке не влияет на другие потоки.

3️⃣Безопасность:
Встроенное шифрование: Все данные, передаваемые по протоколу QUIC, зашифрованы, что повышает уровень безопасности.
Современные алгоритмы шифрования: Использует современные криптографические методы для обеспечения защиты данных.

Особенности:

Поддержка в браузерах и серверах: Многие современные браузеры, такие как Google Chrome и Mozilla Firefox, уже поддерживают HTTP/3. Большие веб-сервисы, такие как Google и Facebook, начали внедрение поддержки HTTP/3 для своих пользователей.
Совместимость: Поскольку HTTP/3 основан на UDP, он требует поддержки со стороны сетевой инфраструктуры (например, брандмауэров и прокси-серверов), чтобы пропускать UDP-трафик.

Хотя конкретный пример кода, показывающий HTTP/3 в действии, зависит от библиотек и инструментов, используемых для разработки, вот как это может выглядеть с использованием библиотеки quic-go .
package main

import (
"fmt"
"net/http"
"github.com/lucas-clemente/quic-go/http3"
)

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

func main() {
http.HandleFunc("/", helloHandler)

server := http3.Server{
Addr: ":443",
Handler: http.DefaultServeMux,
}

fmt.Println("Starting server on https://localhost:443")
err := server.ListenAndServeTLS("path/to/cert.pem", "path/to/key.pem")
if err != nil {
fmt.Println("Error starting server:", err)
}
}


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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Каково стандартное поведение в Go при передаче функции ?
Спросят с вероятностью 17%

Функции являются первоклассными гражданами (first-class citizens), что означает, что функции могут быть переданы в качестве аргументов другим функциям, возвращены из функций, присвоены переменным и храниться в структурах. Рассмотрим основные аспекты поведения при передаче функций в Go.

Передача функции в качестве аргумента

Можно передать в другую функцию в качестве аргумента. Это часто используется для реализации обратных вызовов (callbacks) и функционального программирования.
package main

import "fmt"

// Определение функции, принимающей другую функцию в качестве аргумента
func applyOperation(x int, y int, operation func(int, int) int) int {
return operation(x, y)
}

// Определение простых арифметических функций
func add(a int, b int) int {
return a + b
}

func multiply(a int, b int) int {
return a * b
}

func main() {
a, b := 5, 10

// Передача функции сложения
sum := applyOperation(a, b, add)
fmt.Println("Sum:", sum) // Вывод: Sum: 15

// Передача функции умножения
product := applyOperation(a, b, multiply)
fmt.Println("Product:", product) // Вывод: Product: 50
}


В этом примере функция applyOperation принимает два целых числа и функцию operation, которая выполняет операцию над этими числами. В функции main мы передаем функции add и multiply в applyOperation.

Возврат функции из функции

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

import "fmt"

// Определение функции, возвращающей другую функцию
func createMultiplier(factor int) func(int) int {
return func(x int) int {
return x * factor
}
}

func main() {
// Создание функции, умножающей на 2
double := createMultiplier(2)
fmt.Println("Double 5:", double(5)) // Вывод: Double 5: 10

// Создание функции, умножающей на 3
triple := createMultiplier(3)
fmt.Println("Triple 5:", triple(5)) // Вывод: Triple 5: 15
}


В данном примере функция createMultiplier возвращает анонимную функцию, которая умножает переданное значение на заданный множитель.

Функции как переменные

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

import "fmt"

// Определение простой функции
func greet(name string) {
fmt.Println("Hello,", name)
}

func main() {
// Присваивание функции переменной
var sayHello func(string)
sayHello = greet

// Вызов функции через переменную
sayHello("Alice") // Вывод: Hello, Alice
}


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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Какие бывают версии HTTP ?
Спросят с вероятностью 8%

HTTP (Hypertext Transfer Protocol) — это протокол, используемый для передачи данных. Существует несколько версий HTTP, каждая из которых вносит улучшения и новые возможности по сравнению с предыдущими версиями. Вот основные версии HTTP и их ключевые особенности.

HTTP/0.9

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


Дата выпуска: 1991 год.
Описание: Первая версия протокола, разработанная для передачи простых HTML-страниц.
Ограничения:
Поддерживает только GET-запросы.
Нет поддержки заголовков (headers).
Нет поддержки разных типов контента.

Пример:

Запроса
GET /index.html


Ответа
<html>
<body>
Hello, World!
</body>
</html>


HTTP/1.0

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


Дата выпуска: 1996 год.
Нововведения:
Введение методов запросов: GET, POST, HEAD.
Поддержка заголовков (headers) для метаданных.
Поддержка разных типов контента с использованием заголовка Content-Type.

Пример:

Запроса
GET /index.html HTTP/1.0
Host: www.example.com


Ответа
HTTP/1.0 200 OK
Content-Type: text/html

<html>
<body>
Hello, World!
</body>
</html>


HTTP/1.1

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


Дата выпуска: 1997 год.
Нововведения:
Поддержка постоянных соединений (persistent connections) с использованием Connection: keep-alive.
Введение метода OPTIONS и поддержка новых заголовков.
Поддержка чанковой передачи (chunked transfer encoding).
Поддержка кэширования и улучшенные механизмы управления кэшом.
Введение многократных хостов на одном сервере (host headers).

Пример:

Запроса
GET /index.html HTTP/1.1
Host: www.example.com
Connection: keep-alive


Ответа
HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked

<html>
<body>
Hello, World!
</body>
</html>


HTTP/2

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


Дата выпуска: 2015 год.
Нововведения:
Поддержка бинарного формата вместо текстового, что увеличивает эффективность передачи данных.
Мультиплексирование (multiplexing), позволяющее отправлять несколько запросов и получать ответы одновременно по одному соединению.
Сжатие заголовков (header compression) с использованием алгоритма HPACK.
Серверное пуш-уведомление (server push), позволяющее серверу отправлять данные клиенту без явного запроса.

Пример:

Запроса (примерный)
:method: GET
:path: /index.html
:scheme: https
:authority: www.example.com


Ответа (примерный)
:status: 200
content-type: text/html
content-length: 123

<html>
<body>
Hello, World!
</body>
</html>


HTTP/3

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


Дата выпуска: 2020 год (черновая версия).
Нововведения:
Использование протокола QUIC вместо TCP для улучшения скорости и надежности передачи данных.
Встроенное шифрование всех данных, что повышает безопасность.
Улучшение производительности за счет сокращения времени установления соединения и более эффективного управления потерями пакетов.

Пример:

Запроса (примерный)
:method: GET
:path: /index.html
:scheme: https
:authority: www.example.com


Ответа (примерный)
:status: 200
content-type: text/html
content-length: 123

<html>
<body>
Hello, World!
</body>
</html>


Каждая версия HTTP приносила улучшения и новые возможности для увеличения скорости, надежности и безопасности передачи данных. Переход от HTTP/0.9 к HTTP/3 демонстрирует значительный прогресс в развитии протокола, направленный на удовлетворение современных требований к веб-приложениям и интернет-сервисам.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Forwarded from easyoffer
Канал приближается к 20к подписчиков, а здесь так и нет нормального контент плана 😒

Ищу талантливых журналистов, способных писать клевые и авторские посты на тему "Карьера в IT" и все что с этим связано: поиск работы, повышение з/п, разбор кейсов, переезд в другие страны по рабочим визам, аналитика, исследование рынка и т.д.

Важно глубокое понимание IT индустрии, вы должны иметь опыт работы в ней

Если интересно отправьте мне свое резюме @kivaiko
🤔 Какой механизм в Go используется для обработки исключительных ситуаций?
Anonymous Quiz
8%
try и catch
5%
Исключения
64%
Паника и восстановление
23%
Ошибки возврата
Какие преимущества есть у Go ?
Спросят с вероятностью 17%

Go (или Golang) обладает рядом преимуществ, которые делают его популярным. Рассмотрим основные из них:

1️⃣Простота и лаконичность
Был разработан с упором на простоту синтаксиса и лаконичность. Это делает язык легким для изучения и чтения кода. Минимализм языка позволяет разработчикам сосредоточиться на решении задач, а не на сложностях синтаксиса.

2️⃣Высокая производительность
Компилируется в машинный код, что обеспечивает высокую производительность выполнения программ. Производительность Go сопоставима с производительностью программ, написанных на C или C++, благодаря низкоуровневой оптимизации компилятора.

3️⃣Параллелизм и конкурентность
Одним из ключевых преимуществ является встроенная поддержка параллелизма и конкурентности. С помощью горутин и каналов разработчики могут легко создавать многопоточные приложения.

Пример:
package main

import (
"fmt"
"time"
)

func say(s string) {
for i := 0; i < 3; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}

func main() {
go say("world")
say("hello")
}


В этом примере функция say запускается как горутина с помощью go say("world"), что позволяет выполнять её конкурентно с основной программой.

4️⃣Сильная система типов и безопасность памяти
Имеет строгую систему типов, которая помогает предотвращать ошибки на этапе компиляции. В языке отсутствуют неявные преобразования типов, что снижает вероятность ошибок. Также Go управляет памятью с помощью встроенного сборщика мусора (garbage collector), что предотвращает утечки памяти.

5️⃣Встроенная поддержка стандартных инструментов
Поставляется с богатым набором встроенных инструментов для разработки, таких как:

go fmt для автоматического форматирования кода.
go test для запуска тестов.
go build и go run для сборки и выполнения программ.
go doc для генерации документации.

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

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

8️⃣Сообщество и поддержка
Имеет большое и активное сообщество, а также поддерживается компанией Google. Это гарантирует наличие множества ресурсов для обучения и решения возникающих вопросов, а также активное развитие и улучшение языка.

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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Как инкапсуляция осуществлена в Golang ?
Спросят с вероятностью 17%

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

Экспортируемые и неэкспортируемые элементы

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

Пример инкапсуляции

Определение структуры с экспортируемыми и неэкспортируемыми полями
package main

import (
"fmt"
)

// Person структура с экспортируемыми и неэкспортируемыми полями
type Person struct {
Name string // Экспортируемое поле
age int // Неэкспортируемое поле
}

// Метод для получения возраста (экспортируемый)
func (p *Person) GetAge() int {
return p.age
}

// Метод для установки возраста (экспортируемый)
func (p *Person) SetAge(age int) {
if age >= 0 {
p.age = age
}
}

func main() {
// Создание экземпляра структуры
person := Person{Name: "Alice"}

// Доступ к экспортируемому полю
fmt.Println("Name:", person.Name)

// Установка и получение значения через методы
person.SetAge(30)
fmt.Println("Age:", person.GetAge())
}


В этом примере структура Person имеет экспортируемое поле Name и неэкспортируемое поле age. Методы GetAge и SetAge позволяют управлять доступом к полю age.

Попробуем обратиться к полю age из другого пакета:

Пакет main.go
package main

import (
"fmt"
"mypackage"
)

func main() {
person := mypackage.NewPerson("Bob", 25)

// Доступ к экспортируемому полю
fmt.Println("Name:", person.Name)

// Попытка доступа к неэкспортируемому полю приведет к ошибке компиляции
// fmt.Println("Age:", person.age)

// Использование методов для доступа к неэкспортируемому полю
fmt.Println("Age:", person.GetAge())
}


Пакет mypackage/person.go
package mypackage

// Person структура с экспортируемыми и неэкспортируемыми полями
type Person struct {
Name string // Экспортируемое поле
age int // Неэкспортируемое поле
}

// NewPerson конструктор для создания новой структуры Person
func NewPerson(name string, age int) *Person {
return &Person{Name: name, age: age}
}

// Метод для получения возраста (экспортируемый)
func (p *Person) GetAge() int {
return p.age
}

// Метод для установки возраста (экспортируемый)
func (p *Person) SetAge(age int) {
if age >= 0 {
p.age = age
}
}


В данном примере пакет mypackage определяет структуру Person и функции для работы с неэкспортируемым полем age. Пакет main использует эти функции для управления доступом к полю age.

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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Какой интерфейс в Go используется для обобщенного программирования?
Anonymous Quiz
2%
error
3%
fmt.Stringer
13%
reflect.Type
82%
interface{}
Можно ли сделать int(string) и string(int) соответственно ?
Спросят с вероятностью 8%

Существуют встроенные функции для преобразования типов, включая преобразование из строки в целое число и наоборот. Для этих целей используются функции из стандартной библиотеки 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)
}
}


В этом примере строка "123" успешно преобразуется в целое число 123. Если строка не может быть преобразована (например, содержит нецифровые символы), функция strconv.Atoi вернет ошибку.

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

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

import (
"fmt"
"strconv"
)

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


В этом примере целое число 123 успешно преобразуется в строку "123".

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

Важно обрабатывать ошибки при преобразовании типов, особенно при преобразовании строки в целое число, чтобы избежать неожиданных сбоев в программе.
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)
}
}


В этом примере строка "abc" не может быть преобразована в целое число, поэтому функция strconv.Atoi вернет ошибку, которая будет обработана и выведена на экран.

Для преобразования строки в целое число в Go используется функция strconv.Atoi, а для преобразования целого числа в строку — функция strconv.Itoa. Обработка ошибок при преобразовании строки в целое число необходима для надежности программы.

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Какой метод в Go позволяет безопасно завершить выполнение горутины?
Anonymous Quiz
13%
go exit
57%
context.Done()
12%
goroutine.Stop()
18%
runtime.Goexit()
Какие есть плюсы и минусы у монолита ?
Спросят с вероятностью 8%

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

Плюсы

1️⃣Простота разработки:
Легче начать разработку, особенно для небольших проектов. Вся кодовая база находится в одном месте, что упрощает понимание и внесение изменений.

2️⃣Единая кодовая база:
Весь код хранится в одном репозитории, что упрощает управление версиями, интеграцию изменений и сотрудничество между разработчиками.

3️⃣Простота развертывания:
Разворачивание монолитного приложения проще, так как нужно развернуть только один исполняемый файл или пакет. Нет необходимости в сложной координации развертывания множества микросервисов.

4️⃣Производительность:
Вызовы между компонентами происходят внутри одного процесса, что устраняет накладные расходы на межпроцессное взаимодействие и сетевые задержки.

5️⃣Единая система логирования и мониторинга:
Проще настраивать логирование и мониторинг, так как все компоненты приложения находятся в одном процессе и используют единые средства для логирования и мониторинга.

Минусы

1️⃣Сложность масштабирования:
Трудно масштабировать только определенные части приложения. Если одна часть приложения требует больше ресурсов, приходится масштабировать все приложение целиком, что может быть неэффективно.

2️⃣Сложность поддержки и обновления:
Изменение одного компонента может потребовать повторного развертывания всего приложения. Это увеличивает риски и время развертывания.

3️⃣Ограниченная гибкость:
Использование одной технологии для всего приложения может быть ограничивающим. Трудно использовать разные языки программирования и технологии для разных компонентов.

4️⃣Долгое время старта:
По мере роста приложения время старта может значительно увеличиваться, что влияет на производительность разработки и развертывания.

5️⃣Трудности в разделении команд:
Разработчики могут сталкиваться с конфликтами и сложностями в управлении большими кодовыми базами. Трудно разделить работу над разными частями приложения между командами.

Пример преимуществ и недостатков в реальных сценариях

Пример 1: Простота разработки


Сценарий: Стартап, который разрабатывает MVP (минимально жизнеспособный продукт).

Преимущество: Монолитная архитектура позволяет быстро начать разработку и сосредоточиться на создании основных функций без сложной инфраструктуры.

Пример 2: Сложность масштабирования

Сценарий: Веб-приложение, в котором один из модулей (например, модуль обработки изображений) испытывает высокую нагрузку.

Недостаток: При монолитной архитектуре необходимо масштабировать все приложение, что неэффективно, поскольку другие модули могут не требовать дополнительных ресурсов.

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

👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 349 вопроса на Golang разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🤔 Какой интерфейс в Go должен реализовать тип для использования в sort.Sort?
Anonymous Quiz
44%
Sortable
11%
Less
25%
Comparator
19%
Interface