Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
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
👍2🔥1
Под капотом может происходить множественное выделение памяти, особенно при частых склеиваниях.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Это версии протокола HTTP, каждая из которых имеет свои особенности и улучшения по сравнению с предыдущими версиями. Важные различия между этими версиями включают следующие аспекты:
Поддерживает одновременное открытие нескольких TCP соединений (обычно 6-8), что позволяет загружать несколько ресурсов параллельно. Однако каждое соединение может обрабатывать только один запрос за раз, что приводит к задержкам из-за блокировки очереди (head-of-line blocking).
Вводит мультиплексирование, позволяющее отправлять множество запросов и ответов асинхронно через одно единственное TCP соединение. Это значительно уменьшает задержки и улучшает производительность при загрузке страниц с большим количеством ресурсов.
Является текстовым протоколом, что означает, что запросы и ответы форматируются в виде читаемого текста.
Бинарный протокол, который делает передачу данных более эффективной и менее подверженной ошибкам в синтаксическом анализе. Бинарный формат упрощает реализацию парсеров и уменьшает размер передаваемых данных.
Заголовки передаются без сжатия, что может привести к значительному объему передаваемых данных, особенно если одни и те же заголовки отправляются повторно с каждым запросом.
Использует механизм сжатия заголовков HPACK, который уменьшает избыточность заголовков, сжимая их перед отправкой. Это особенно эффективно для повторяющихся запросов к одним и тем же серверам.
Не поддерживает приоритизацию запросов, из-за чего браузеры должны использовать эвристики для управления приоритетами ресурсов.
Поддерживает явную приоритизацию запросов, позволяя клиенту указывать приоритет обработки ресурсов, что делает загрузку страниц более эффективной.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Foreign key (внешний ключ) — это ограничение в базе данных, обеспечивающее связь между таблицами и целостность данных.
Он:
- Предотвращает вставку «висячих» записей (без связанных данных).
- Позволяет БД контролировать каскадное удаление/обновление.
- Делает структуру БД более безопасной и логичной.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2💊1
В Go пустой интерфейс
interface{} является особым типом, который может содержать значение любого типа. Это связано с тем, что в Go любой тип реализует пустой интерфейс, поскольку в нем нет методов, которые нужно реализовать. Поскольку пустой интерфейс не требует реализации каких-либо методов, любой тип в Go автоматически реализует этот интерфейс. Это делает пустой интерфейс универсальным контейнером для значений любых типов.
type interface{} interface {}Типа конкретного значения
Самого значения
Когда значение присваивается переменной типа интерфейс, Go сохраняет информацию о типе и значении этого значения. Для пустого интерфейса эта информация может быть любого типа.
Когда значение из пустого интерфейса приводится к конкретному типу, происходит проверка типа во время выполнения. Если значение внутри интерфейса действительно является указанным типом, приведение успешно. В противном случае приведение не удается, и возвращается значение
nil или происходит паника, если приведение выполнено без проверки.Присваивание значений пустому интерфейсу
package main
import "fmt"
func main() {
var i interface{}
i = 42
fmt.Println(i) // 42
i = "hello"
fmt.Println(i) // hello
}
Утверждение типа (Type Assertion)
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")
}
// Утверждение типа без проверки
// Это вызовет панику, если тип не соответствует
s = i.(string)
fmt.Println("String:", s)
}
Использование switch для проверки типа
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)
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
len и capacity в слайсе Go? 2. capacity: общая ёмкость слайса, включая длину и свободное пространство, доступное для добавления новых элементов
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Это предопределенное идентификатор, используемое для создания последовательностей целочисленных констант. Он применяется в контексте объявления констант и автоматически инкрементируется на единицу с каждым новым значением. Обычно используется для определения множества связанных констант без необходимости вручную назначать каждому элементу значение.
Начинает счет с 0 в каждой новой группе констант.
Каждое последующее использование
iota в одной группе констант увеличивает его значение на 1.При каждом новом объявлении константного блока
iota сбрасывается до 0.package main
import "fmt"
const (
A = iota // 0
B // 1
C // 2
)
func main() {
fmt.Println(A) // Вывод: 0
fmt.Println(B) // Вывод: 1
fmt.Println(C) // Вывод: 2
}
Использование его для создания битовых флагов
package main
import "fmt"
const (
Flag1 = 1 << iota // 1 << 0 = 1
Flag2 // 1 << 1 = 2
Flag3 // 1 << 2 = 4
Flag4 // 1 << 3 = 8
)
func main() {
fmt.Println(Flag1) // Вывод: 1
fmt.Println(Flag2) // Вывод: 2
fmt.Println(Flag3) // Вывод: 4
fmt.Println(Flag4) // Вывод: 8
}
Сброс его в новом блоке
package main
import "fmt"
const (
X = iota // 0
Y // 1
)
const (
Z = iota // 0 (новый блок констант, iota сбрасывается)
W // 1
)
func main() {
fmt.Println(X) // Вывод: 0
fmt.Println(Y) // Вывод: 1
fmt.Println(Z) // Вывод: 0
fmt.Println(W) // Вывод: 1
}
Можно использовать в выражениях и совместно с другими константами для создания более сложных последовательностей.
package main
import "fmt"
const (
_ = iota // пропускаем 0
KB = 1 << (10 * iota) // 1 << 10 = 1024
MB // 1 << 20 = 1048576
GB // 1 << 30 = 1073741824
)
func main() {
fmt.Println("KB:", KB) // Вывод: KB: 1024
fmt.Println("MB:", MB) // Вывод: MB: 1048576
fmt.Println("GB:", GB) // Вывод: GB: 1073741824
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍1
Линтеры — это инструменты для автоматической проверки кода на ошибки, потенциальные баги и несоответствие стилю кодирования.
В Go есть несколько популярных линтеров:
golangci-lint – самый мощный и популярный, объединяет множество линтеров. go vet – стандартный инструмент для поиска ошибок. golint – проверяет стиль кода (но устарел). staticcheck – анализирует код на ошибки и неэффективность. Устанавливаем
golangci-lint (лучший вариант) go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
После установки проверьте версию:
golangci-lint --version
Запустить проверку в проекте можно так:
golangci-lint run
Можно проверить только определённый файл:
golangci-lint run myfile.go
Если хотите автоматически исправлять ошибки, используйте:
golangci-lint run --fix
Go уже имеет встроенный линтер
go vet ./...
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
В Go функция может возвращать несколько значений одновременно, благодаря множественному возврату.
Ограничений по количеству возвратов формально нет (можно вернуть хоть 10 переменных), но по стилю рекомендуется не перегружать сигнатуру — до 2–3 значений максимум, особенно если не используются именованные возвращаемые значения.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤔1
В языке 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() // Вызов метода встроенной структуры
}
Определяют набор методов, которые должны быть реализованы типом. Любой тип, реализующий все методы интерфейса, автоматически рассматривается как реализующий этот интерфейс. Это дает возможность полиморфизма.
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)
}
Интерфейсы также могут быть встроены друг в друга, что позволяет создавать сложные структуры интерфейсов.
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()
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
- Нет классов, используется композиция через структуры и методы.
- Полиморфизм достигается с помощью интерфейсов.
- Наследования нет, встраивание заменяет его.
2. C#:
- Полноценное ООП: классы, наследование, абстракция, интерфейсы.
- Поддержка модификаторов доступа (public, private, protected).
- Разработано для объектно-ориентированной модели с полной поддержкой инкапсуляции и полиморфизма.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊4👍1
Это структура данных, которая используется для хранения и поиска пар "ключ-значение". Обеспечивают быстрый доступ к данным по ключу, обычно с константным временем доступа в среднем случае. Основой работы хэш-таблицы является хеш-функция, которая преобразует ключ в индекс, по которому хранится значение.
Функция, которая принимает ключ и преобразует его в индекс массива, называемого "хэш-таблицей". Хорошая хеш-функция распределяет ключи равномерно по хэш-таблице, минимизируя количество коллизий.
Массив фиксированного размера, где каждый элемент называется "корзиной" (bucket). Корзина может содержать одно или несколько значений.
Ситуация, когда два разных ключа хешируются в один и тот же индекс. Коллизии решаются с помощью различных методов, таких как цепочки (chaining) или открытая адресация (open addressing).
Хеш-функция вычисляет индекс для данного ключа. Значение помещается в соответствующую корзину по этому индексу. Если возникает коллизия, используется метод разрешения коллизий.
Хеш-функция вычисляет индекс для ключа. Корзина по этому индексу проверяется на наличие значения. Если значение найдено, оно возвращается; если нет, возвращается индикатор отсутствия значения.
Хеш-функция вычисляет индекс для ключа. Значение удаляется из соответствующей корзины. При необходимости корректируются ссылки или структура данных для разрешения коллизий.
Среднее время доступа к элементу составляет O(1).
Обеспечивает простой интерфейс для вставки, поиска и удаления данных.
Требуют дополнительных механизмов для разрешения, что может усложнить реализацию.
Эффективность хэш-таблицы зависит от качества хеш-функции.
При увеличении количества элементов может потребоваться перераспределение и увеличение размера таблицы, что временно снижает производительность.
package main
import "fmt"
func main() {
// Создание карты
myMap := make(map[string]int)
// Вставка значений
myMap["Alice"] = 25
myMap["Bob"] = 30
// Поиск значений
value, exists := myMap["Alice"]
if exists {
fmt.Println("Alice:", value) // Alice: 25
} else {
fmt.Println("Alice not found")
}
// Удаление значений
delete(myMap, "Alice")
_, exists = myMap["Alice"]
if !exists {
fmt.Println("Alice has been deleted") // Alice has been deleted
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Примитивы — это средства, предотвращающие конфликты между потоками:
- Mutex — взаимное исключение.
- Semaphore — ограничение количества одновременных доступов.
- Spinlock — цикл ожидания без сна.
- RWLock (чтение-запись) — позволяет множественное чтение, но только одну запись.
- Atomic операции — безопасные базовые действия без блокировок.
- Condition variables — ожидание события от другого потока.
- Channel / Queue — для безопасного обмена данными (особенно в Go).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
Слайс (
slice) — это динамический массив, который ссылается на часть массива в памяти. В отличие от массивов (array), слайсы могут изменять размер. Слайс в Go — это структура
type SliceHeader struct {
Data uintptr // Указатель на массив в памяти
Len int // Длина слайса (количество элементов)
Cap int // Вместимость (capacity) — сколько элементов может вместить без перевыделения памяти
}Пример структуры слайса
arr := [5]int{1, 2, 3, 4, 5}
s := arr[1:4] // Берём срез от 2-го до 4-го элемента
fmt.Println(s) // [2 3 4]Есть несколько способов создать слайс:
Способ 1: Срез массива
arr := [5]int{10, 20, 30, 40, 50}
s := arr[1:4] // [20 30 40]Способ 2: Использование
make()s := make([]int, 3, 5) // Длина 3, вместимость 5
fmt.Println(s, len(s), cap(s)) // [0 0 0] 3 5
Способ 3: Литерал (инициализация значениями)
s := []int{1, 2, 3}
fmt.Println(s) // [1 2 3]Слайсы можно изменять, используя
append(). s := []int{1, 2, 3}
s = append(s, 4, 5)
fmt.Println(s) // [1 2 3 4 5]Когда
append() увеличивает slice, Go использует оптимизированный алгоритм роста:- Если
cap < 1024, слайс удваивает размер (cap *= 2). - Если
cap >= 1024, рост идёт примерно на 25% (cap += cap / 4). s := []int{}
for i := 0; i < 10; i++ {
s = append(s, i)
fmt.Printf("Len: %d, Cap: %d\n", len(s), cap(s))
}Выход (пример)
Len: 1, Cap: 1
Len: 2, Cap: 2
Len: 3, Cap: 4
Len: 5, Cap: 8
Len: 9, Cap: 16
Так как слайсы хранят ссылку на массив, возможны побочные эффекты.
arr := [5]int{1, 2, 3, 4, 5}
s1 := arr[:3] // [1 2 3]
s2 := arr[2:] // [3 4 5]
s2[0] = 100 // Меняем первый элемент s2
fmt.Println(s1) // [1 2 100] ❗️ s1 тоже изменилсяРешение: используйте
copy() для создания нового массива. s1 := []int{1, 2, 3}
s2 := make([]int, len(s1))
copy(s2, s1) // Копируем данные
s2[0] = 100
fmt.Println(s1) // [1 2 3] ✅ Оригинал не изменилсяСтавь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Media is too big
VIEW IN TELEGRAM
На программиста, тестировщика, аналитика, проджекта и другие IT профы.
Есть собесы от ведущих компаний: Сбер, Яндекс, ВТБ, Тинькофф, Озон, Wildberries и т.д.
🎯 Переходи по ссылке и присоединяйся к базе, чтобы прокачать свои шансы на успешное трудоустройство!
Please open Telegram to view this post
VIEW IN TELEGRAM
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1