Golang | Вопросы собесов
4.33K subscribers
26 photos
694 links
Download Telegram
🤔 Какое ключевое слово используется для импорта пакета в Go?
Anonymous Quiz
3%
include
2%
require
94%
import
1%
use
🤔 Как можно откопировать слайс ?

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


Принимает два аргумента: целевой срез и исходный срез. Она копирует элементы из исходного среза в целевой и возвращает количество скопированных элементов. В этом примере исходный срез src копируется в целевой срез dst. Размер целевого среза должен быть равен или больше размера исходного среза, чтобы все элементы могли быть скопированы.
package main

import "fmt"

func main() {
// Исходный срез
src := []int{1, 2, 3, 4, 5}

// Целевой срез, который должен иметь достаточно места для копирования элементов
dst := make([]int, len(src))

// Копирование среза
n := copy(dst, src)

// Вывод результатов
fmt.Println("Исходный срез:", src) // Output: Исходный срез: [1 2 3 4 5]
fmt.Println("Целевой срез:", dst) // Output: Целевой срез: [1 2 3 4 5]
fmt.Println("Количество скопированных элементов:", n) // Output: Количество скопированных элементов: 5
}


Частичное копирование: Если целевой срез меньше исходного, copy скопирует только столько элементов, сколько поместится в целевой срез.
package main

import "fmt"

func main() {
// Исходный срез
src := []int{1, 2, 3, 4, 5}

// Целевой срез меньшего размера
dst := make([]int, 3)

// Копирование среза
n := copy(dst, src)

// Вывод результатов
fmt.Println("Исходный срез:", src) // Output: Исходный срез: [1 2 3 4 5]
fmt.Println("Целевой срез:", dst) // Output: Целевой срез: [1 2 3]
fmt.Println("Количество скопированных элементов:", n) // Output: Количество скопированных элементов: 3
}


Копирование разных типов: Функция copy работает только с срезами одного типа. Если вы попытаетесь копировать элементы между срезами разных типов, это приведет к ошибке компиляции.
package main

import "fmt"

func main() {
// Исходный срез
src := []int{1, 2, 3, 4, 5}

// Целевой срез
dst := make([]int, 2)

// Копирование части среза
n := copy(dst, src[1:3])

// Вывод результатов
fmt.Println("Исходный срез:", src) // Output: Исходный срез: [1 2 3 4 5]
fmt.Println("Целевой срез:", dst) // Output: Целевой срез: [2 3]
fmt.Println("Количество скопированных элементов:", n) // Output: Количество скопированных элементов: 2
}


Глубокое копирование срезов с вложенными структурами: Если он содержит сложные структуры данных, такие как структуры или срезы с указателями, вам может понадобиться реализовать глубокое копирование, чтобы копировать не только сами элементы, но и данные, на которые они ссылаются.
package main

import "fmt"

type Item struct {
Value int
}

func main() {
// Исходный срез
src := []Item{{1}, {2}, {3}}

// Целевой срез
dst := make([]Item, len(src))

// Глубокое копирование
for i, item := range src {
dst[i] = Item{Value: item.Value}
}

// Изменение исходного среза не влияет на целевой срез
src[0].Value = 100

// Вывод результатов
fmt.Println("Исходный срез:", src) // Output: Исходный срез: [{100} {2} {3}]
fmt.Println("Целевой срез:", dst) // Output: Целевой срез: [{1} {2} {3}]
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Какой тип используется для представления динамических массивов в Go?
Anonymous Quiz
6%
array
3%
list
86%
slice
6%
map
🤔 Что такое моки (mocks) ?

Моки (mocks) — это объекты, которые имитируют поведение реальных объектов в тестах. Они используются для изоляции тестируемого кода от зависимостей, таких как базы данных, внешние API, файловая система и другие сервисы. Моки позволяют сосредоточиться на тестировании конкретной части кода без необходимости задействовать реальные ресурсы, что делает тесты более быстрыми и предсказуемыми.

🚩 Зачем они нужны?

🟠Изоляция тестов: Позволяют изолировать тестируемый код от его зависимостей, что помогает убедиться, что тестируемая логика работает правильно сама по себе.
🟠Контроль над средой тестирования: С моками можно точно контролировать возвращаемые значения и поведение зависимостей, что позволяет создавать предсказуемые и повторяемые тесты.
🟠Ускорение тестов: Использование моков вместо реальных ресурсов (таких как базы данных или внешние API) делает тесты быстрее и снижает затраты на их выполнение.
🟠Тестирование ошибок и крайних случаев: Позволяют легко моделировать ошибки и крайние случаи, которые могут быть трудно воспроизвести с реальными зависимостями.

🚩Как их использовать моки ?

Для создания и использования их часто используют специальные библиотеки, такие как gomock или testify/mock. Рассмотрим пример использования библиотеки testify/mock.

Установка библиотеки testify
go get github.com/stretchr/testify


// api.go
package main

type APIClient interface {
FetchData(endpoint string) (string, error)
}

func GetData(client APIClient, endpoint string) (string, error) {
data, err := client.FetchData(endpoint)
if err != nil {
return "", err
}
return data, nil
}


Создадим мок для интерфейса APIClient с использованием библиотеки testify/mock.
// api_test.go
package main

import (
"errors"
"testing"

"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/assert"
)

// MockAPIClient is a mock type for the APIClient interface
type MockAPIClient struct {
mock.Mock
}

func (m *MockAPIClient) FetchData(endpoint string) (string, error) {
args := m.Called(endpoint)
return args.String(0), args.Error(1)
}

func TestGetData(t *testing.T) {
// Создание мока
mockClient := new(MockAPIClient)

// Настройка мока для возврата данных
mockClient.On("FetchData", "test-endpoint").Return("mocked data", nil)

// Вызов тестируемой функции
data, err := GetData(mockClient, "test-endpoint")

// Проверка результатов
assert.NoError(t, err)
assert.Equal(t, "mocked data", data)

// Проверка вызова мока
mockClient.AssertExpectations(t)
}

func TestGetDataWithError(t *testing.T) {
// Создание мока
mockClient := new(MockAPIClient)

// Настройка мока для возврата ошибки
mockClient.On("FetchData", "error-endpoint").Return("", errors.New("fetch error"))

// Вызов тестируемой функции
data, err := GetData(mockClient, "error-endpoint")

// Проверка результатов
assert.Error(t, err)
assert.Equal(t, "", data)

// Проверка вызова мока
mockClient.AssertExpectations(t)
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Какой пакет используется для работы с регулярными выражениями в Go?
Anonymous Quiz
40%
regex
11%
reg
8%
re
42%
regexp
🤔 Что возвращает оператор "квадратные скобки" для строки ?

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

package main

import "fmt"

func main() {
str := "hello"

// Получение первого символа строки
firstChar := str[0]

// Вывод значения байта
fmt.Printf("Первый символ: %c\n", firstChar) // Output: Первый символ: h

// Вывод байтового значения
fmt.Printf("Байтовое значение: %d\n", firstChar) // Output: Байтовое значение: 104
}


В этом примере str[0] возвращает байт, представляющий первый символ строки "hello", который является символом 'h' и имеет байтовое значение 104.

🚩Доступ к символам

🟠Байт по индексу: Каждый символ строки хранится как один или несколько байтов, и str[i] возвращает байт, соответствующий i-тому индексу.
🟠Срез строки: Можно получить срез строки с помощью оператора [:], который также возвращает новую строку.
substr := str[1:4]
fmt.Println(substr) // Output: ell


Так как строки в Go являются последовательностями байтов, они могут содержать символы Unicode, которые могут занимать более одного байта. Для правильной обработки Unicode символов нужно использовать пакет unicode/utf8.
package main

import (
"fmt"
"unicode/utf8"
)

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

// Получение первого символа Unicode
runeValue, size := utf8.DecodeRuneInString(str)

fmt.Printf("Первый символ: %c\n", runeValue) // Output: Первый символ: П
fmt.Printf("Размер в байтах: %d\n", size) // Output: Размер в байтах: 2
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Какой метод интерфейса io.Reader используется для чтения данных?
Anonymous Quiz
69%
Read
28%
Scan
3%
Fetch
0%
Receive
🤔 Как будет происходить вставка в Map ?

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

🚩Создание карты

Прежде чем вставить элементы в карту, необходимо ее создать. Карты в Go могут быть созданы с использованием встроенной функции make или литерала карты.

Создание карты с использованием make: Здесь мы создаем карту myMap, которая использует строки в качестве ключей и целые числа в качестве значений.
myMap := make(map[string]int)


Создание карты с использованием литерала карты: В этом примере мы создаем карту и сразу инициализируем ее несколькими значениями.
myMap := map[string]int{
"one": 1,
"two": 2,
}


Вставка элементов в карту: В этом примере мы создаем пустую карту myMap и вставляем в нее три пары ключ-значение. Ключи — это строки ("one", "two", "three"), а значения — целые числа (1, 2, 3). Когда мы присваиваем значение конкретному ключу (myMap["one"] = 1), Go автоматически добавляет эту пару в карту.
package main

import "fmt"

func main() {
// Создание карты
myMap := make(map[string]int)

// Вставка элементов
myMap["one"] = 1
myMap["two"] = 2
myMap["three"] = 3

// Вывод карты
fmt.Println(myMap)
}


Обновление элементов карты: Здесь значение ключа "two" обновляется с 2 на 22, а новый ключ "three" добавляется со значением 3.
func main() {
// Создание и инициализация карты
myMap := map[string]int{
"one": 1,
"two": 2,
}

// Обновление значения существующего ключа
myMap["two"] = 22

// Добавление нового ключа
myMap["three"] = 3

// Вывод карты
fmt.Println(myMap)
}


🚩Проверка наличия ключа и удаление элементов

Для проверки, существует ли ключ в карте, используется конструкция с двумя возвращаемыми значениями:
value, exists := myMap["two"]
if exists {
fmt.Println("Key 'two' exists with value:", value)
} else {
fmt.Println("Key 'two' does not exist")
}


Для удаления элемента из карты используется встроенная функция delete:
delete(myMap, "two")
fmt.Println("After deletion:", myMap)


package main

import "fmt"

func main() {
// Создание карты
myMap := make(map[string]int)

// Вставка элементов
myMap["one"] = 1
myMap["two"] = 2
myMap["three"] = 3

// Обновление элемента
myMap["two"] = 22

// Проверка наличия ключа
value, exists := myMap["two"]
if exists {
fmt.Println("Key 'two' exists with value:", value)
} else {
fmt.Println("Key 'two' does not exist")
}

// Удаление элемента
delete(myMap, "two")
fmt.Println("After deletion:", myMap)
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Какое значение имеет переменная m["key"] после удаления ключа в Go?
Anonymous Quiz
26%
0
1%
1
58%
nil
15%
panic
🤔 Что можно хранить в качестве ключа, если Float не использовать ?

Для ключей в картах (maps) можно использовать типы, которые удовлетворяют определенным требованиям. Ключи должны быть сравнимыми, то есть поддерживать операторы сравнения (== и !=). Это означает, что типы, используемые в качестве ключей, должны иметь возможность быть сравнены на равенство. В Go это включает следующие типы:

🟠Целые числа (int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64): map[int]string, map[int64]int
🟠Строки (string): map[string]int
🟠Булевы значения (bool): map[bool]string
🟠Указатели (например, *int, *struct): map[*int]string
🟠Каналы (chan T): map[chan int]string
🟠Интерфейсы (при условии, что их конкретные значения сравнимы): map[interface{}]string, но конкретные значения, хранимые в интерфейсах, должны быть сравнимы.
🟠Структуры (struct): map[struct{a int; b string}]int

Использование целых чисел в качестве ключей:
package main

import "fmt"

func main() {
intMap := make(map[int]string)
intMap[1] = "one"
intMap[2] = "two"
fmt.Println(intMap) // Output: map[1:one 2:two]
}


Использование строк в качестве ключей:
package main

import "fmt"

func main() {
stringMap := make(map[string]int)
stringMap["one"] = 1
stringMap["two"] = 2
fmt.Println(stringMap) // Output: map[one:1 two:2]
}


Использование структур в качестве ключей:
package main

import "fmt"

type Person struct {
FirstName string
LastName string
}

func main() {
structMap := make(map[Person]int)
structMap[Person{"John", "Doe"}] = 1
structMap[Person{"Jane", "Doe"}] = 2
fmt.Println(structMap) // Output: map[{John Doe}:1 {Jane Doe}:2]
}


Использование указателей в качестве ключей:
package main

import "fmt"

func main() {
int1 := 1
int2 := 2
ptrMap := make(map[*int]string)
ptrMap[&int1] = "one"
ptrMap[&int2] = "two"
fmt.Println(ptrMap) // Output: map[0x...:one 0x...:two]
}


Ограничения
🟠Тип: Хотя типы float32 и float64 могут быть использованы, их использование в качестве ключей в картах не рекомендуется из-за проблем с точностью при сравнении плавающих точек.
🟠Срезы (slices): Не могут быть использованы в качестве ключей, потому что они не сравнимы.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Какое значение имеет переменная после попытки приведения типа, если приведение не удалось?
Anonymous Quiz
31%
Значение по умолчанию для типа
22%
Ошибка времени выполнения
24%
Значение переменной до приведения
24%
nil
🤔 Что такое хэш-коллизия ?

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

🚩Как возникают коллизии?

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

🚩Управление коллизиями

Существует несколько методов для управления хэш-коллизиями. Два наиболее распространенных метода — это цепочки (chaining) и открытая адресация (open addressing).

🟠Цепочки (Chaining)
В этом методе каждая ячейка хэш-таблицы содержит указатель на список (например, связанный список) всех элементов, которые имеют одно и то же хэш-значение. Когда происходит коллизия, новый элемент просто добавляется в этот список.
type Entry struct {
key string
value int
next *Entry
}

type HashMap struct {
buckets []*Entry
}

func (m *HashMap) Put(key string, value int) {
index := hash(key) % len(m.buckets)
entry := m.buckets[index]
for entry != nil {
if entry.key == key {
entry.value = value
return
}
entry = entry.next
}
m.buckets[index] = &Entry{key: key, value: value, next: m.buckets[index]}
}

func hash(key string) int {
hash := 0
for _, char := range key {
hash += int(char)
}
return hash
}


🟠Открытая адресация (Open Addressing)
В этом методе все элементы хранятся непосредственно в хэш-таблице. Если ячейка, определенная хэш-функцией, уже занята, используется альтернативная стратегия для нахождения следующей доступной ячейки. Наиболее распространенные стратегии включают линейное пробирование (linear probing), квадратичное пробирование (quadratic probing) и двойное хеширование (double hashing).
type HashMap struct {
keys []string
values []int
size int
}

func (m *HashMap) Put(key string, value int) {
index := hash(key) % len(m.keys)
for m.keys[index] != "" {
if m.keys[index] == key {
m.values[index] = value
return
}
index = (index + 1) % len(m.keys)
}
m.keys[index] = key
m.values[index] = value
m.size++
}

func hash(key string) int {
hash := 0
for _, char := range key {
hash += int(char)
}
return hash
}


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

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

🚩Основные особенности HTTP/3

🟠Использование QUIC:
QUIC (Quick UDP Internet Connections) разработан Google и работает поверх UDP, а не TCP. Обеспечить более быструю и надежную передачу данных, улучшить производительность и сократить задержки.

🟠Ускоренное установление соединений:
QUIC значительно сокращает время на установление соединения по сравнению с TCP. Благодаря интеграции с TLS, процесс безопасности и установка соединения происходят одновременно.

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

🟠Мультиплексирование:
HTTP/3 позволяет отправлять несколько запросов и получать ответы через одно соединение одновременно без блокировок, что ускоряет передачу данных и повышает эффективность использования соединений.

🟠Сжатие заголовков:
Новый механизм сжатия заголовков, улучшенный по сравнению с HPACK в HTTP/2, который учитывает особенности QUIC и уменьшает задержки.

🟠Серверное push-сообщение:
Как и в HTTP/2, HTTP/3 поддерживает серверное push-сообщение, позволяя серверу отправлять данные клиенту до их запроса, что ускоряет загрузку страниц.
🚩Плюсы

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

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

Надежность:
Улучшенная устойчивость к сетевым сбоям и потерям пакетов делает соединения более надежными и стабильными.

🚩Минусы

Совместимость:
Поскольку HTTP/3 использует QUIC и UDP, а не TCP, некоторые старые или ограниченные сети и устройства могут не поддерживать этот протокол.

Сложность реализации:
Внедрение и поддержка HTTP/3 требуют новых знаний и навыков, что может усложнить разработку и администрирование.

Инфраструктурные изменения:
Переход на HTTP/3 может требовать обновления серверного оборудования и программного обеспечения для полной поддержки нового протокола.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Какой интерфейс должен реализовывать тип, чтобы его можно было использовать в качестве ключа в map?
Anonymous Quiz
25%
hashable
65%
comparable
8%
keyable
3%
equatable
🤔 Что такое 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
🤔 Как в Go создаются именованные возвращаемые значения?
Anonymous Quiz
71%
func f() (result int)
9%
func f() (result: int)
16%
func f() int result
4%
func f() (result = int)
🤔 Как произвести дебаг protobuff?

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

🟠Использование текстового формата
Protocol Buffers поддерживают сериализацию данных в текстовом формате, который проще для чтения и отладки. Вы можете конвертировать бинарные данные в текстовый формат для более удобной отладки.
// message.proto
syntax = "proto3";

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

// main.go
package main

import (
"fmt"
"log"

"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"your_project_path/your_proto_package" // заменить на реальный путь
)

func main() {
person := &your_proto_package.Person{
Name: "John Doe",
Id: 123,
Email: "john.doe@example.com",
}

// Сериализация в бинарный формат
data, err := proto.Marshal(person)
if err != nil {
log.Fatalf("Failed to marshal: %v", err)
}

// Десериализация обратно в текстовый формат для отладки
person2 := &your_proto_package.Person{}
err = proto.Unmarshal(data, person2)
if err != nil {
log.Fatalf("Failed to unmarshal: %v", err)
}

jsonString, err := protojson.Marshal(person2)
if err != nil {
log.Fatalf("Failed to marshal to JSON: %v", err)
}

fmt.Println(string(jsonString))
}


🟠Использование Protobuf декодеров и редакторов
protoc: Официальный компилятор protobuf, который может генерировать текстовые представления сообщений.
protoc-gen-json: Плагин для protoc, который позволяет сериализовать сообщения в формат JSON.
protoc-inspector: Утилита для визуализации и отладки protobuf сообщений.

🟠Проверка схемы (Proto File)
Убедитесь, что ваша .proto схема правильна и соответствует структуре данных, которую вы пытаетесь сериализовать и десериализовать. Ошибки в схеме могут привести к неправильной сериализации и десериализации данных.

🟠Логирование и трассировка
Добавление логирования и трассировки в код может помочь отслеживать, где происходят ошибки при работе с protobuf.
// main.go
package main

import (
"fmt"
"log"

"google.golang.org/protobuf/proto"
"your_project_path/your_proto_package" // заменить на реальный путь
)

func main() {
person := &your_proto_package.Person{
Name: "John Doe",
Id: 123,
Email: "john.doe@example.com",
}

// Логируем данные до сериализации
fmt.Printf("Before Marshal: %+v\n", person)

// Сериализация в бинарный формат
data, err := proto.Marshal(person)
if err != nil {
log.Fatalf("Failed to marshal: %v", err)
}

// Логируем бинарные данные
fmt.Printf("Binary data: %v\n", data)

// Десериализация
person2 := &your_proto_package.Person{}
err = proto.Unmarshal(data, person2)
if err != nil {
log.Fatalf("Failed to unmarshal: %v", err)
}

// Логируем данные после десериализации
fmt.Printf("After Unmarshal: %+v\n", person2)
}


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

HTTP (HyperText Transfer Protocol) — это протокол, используемый для передачи данных в интернете.

🚩Основные версии HTTP.

🟠HTTP/0.9
Год выпуска: 1991

Особенности
Первая версия HTTP, очень простая. Поддерживала только GET-запросы. Отсутствие заголовков, только один объект мог быть передан в ответ на запрос.

Использование:
В настоящее время практически не используется.

🟠HTTP/1.0
Год выпуска: 1996

Особенности
Введены методы запроса, такие как GET, POST и HEAD. Поддержка заголовков для метаданных. Каждый запрос/ответ требует нового соединения, что делает передачу данных менее эффективной.

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

🟠HTTP/1.1
Год выпуска: 1997

Особенности
Поддержка устойчивых (persistent) соединений, что позволяет повторное использование одного соединения для нескольких запросов/ответов. Введены дополнительные методы запросов, такие как OPTIONS, PUT, DELETE, TRACE и CONNECT. Поддержка chuncked transfer encoding для передачи данных по частям. Улучшена работа с кэшированием и аутентификацией.

Использование
Широко используется и в настоящее время, хотя многие системы переходят на HTTP/2.

🟠HTTP/2
Год выпуска: 2015

Особенности
Бинарный протокол, что улучшает производительность и уменьшает количество ошибок. Поддержка мультиплексирования, что позволяет отправлять несколько запросов через одно соединение одновременно, уменьшая задержки. Сжатие заголовков, что уменьшает объем передаваемых данных. Серверное push-сообщение (server push), позволяющее серверу отправлять данные клиенту до того, как он их запросит.

Использование
Быстро набирает популярность благодаря улучшенной производительности и эффективности.

🟠HTTP/3
Год выпуска: 2022 (черновая версия в 2020)

Особенности
Основан на протоколе QUIC, который работает поверх UDP, а не TCP. Поддержка улучшенного мультиплексирования и быстрого установления соединений. Лучшая устойчивость к потерям пакетов и более высокая скорость передачи данных по сравнению с HTTP/2.

Использование
Внедрение продолжается, но многие крупные интернет-компании, такие как Google и Facebook, уже активно используют HTTP/3.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM