Ключи в map (карте) должны обладать определенными свойствами, чтобы быть допустимыми и корректно работать с хеш-таблицей. Важно понимать, что ключи должны поддерживать операцию сравнения и быть хешируемыми.
Ключи должны поддерживать операцию сравнения с использованием оператора
==. Это необходимо для проверки равенства ключей при выполнении операций вставки, поиска и удаления в карте.Ключи должны быть хешируемыми. Это значит, что для ключей должна существовать функция, которая преобразует их в хеш-код. Хеш-код используется для определения позиции ключа в хеш-таблице.
Булевый тип (bool)
m := map[bool]string{
true: "Yes",
false: "No",
} Целочисленные типы (int, int8, int16, int32, int64, а также их беззнаковые эквиваленты uint, uint8, uint16, uint32, uint64)
m := map[int]string{
1: "One",
2: "Two",
} Числа с плавающей точкой (float32, float64)
m := map[float64]string{
1.1: "One point one",
2.2: "Two point two",
} Строки (string)
m := map[string]int{
"Alice": 25,
"Bob": 30,
}Составные типы (структуры, массивы), при условии, что все их поля также поддерживают сравнение с помощью оператора ==
type Key struct {
FirstName string
LastName string
}
m := map[Key]int{
{"Alice", "Smith"}: 1,
{"Bob", "Johnson"}: 2,
}
slice)Срезы не поддерживают операцию сравнения с использованием оператора
== (только сравнение с nil).map)Карты не поддерживают операцию сравнения.
func)Функции не поддерживают операцию сравнения.
package main
import "fmt"
type Person struct {
FirstName string
LastName string
}
func main() {
// Создаем карту с ключами типа Person
m := make(map[Person]int)
// Вставляем значения в карту
m[Person{"Alice", "Smith"}] = 25
m[Person{"Bob", "Johnson"}] = 30
// Выводим значения из карты
fmt.Println(m[Person{"Alice", "Smith"}]) // Выводит: 25
fmt.Println(m[Person{"Bob", "Johnson"}]) // Выводит: 30
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
2. Каналы для организации потокобезопасного взаимодействия.
3. WaitGroup для ожидания завершения нескольких горутин.
4. Атомарные операции для управления простыми данными.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
В Go строки представляют собой неизменяемые последовательности байтов, и операция сложения строк (
+) приводит к созданию новой строки, которая является конкатенацией двух или более исходных строк. Когда вы складываете строки, Go создает новую строку, содержащую все символы исходных строк, соединенных друг за другом. Исходные строки при этом остаются неизменными.
s1 := "Hello"
s2 := "World"
result := s1 + " " + s2
fmt.Println(result) // Output: Hello World
Так как строки в Go неизменяемы, результирующая строка создается заново, а память для нее выделяется в куче или на стеке, в зависимости от размера и контекста.
Сложение строк через оператор
+ может быть неэффективным при множественных операциях, так как каждый раз создается новая строка, а старые промежуточные результаты удаляются сборщиком мусора.result := ""
for i := 0; i < 5; i++ {
result += "Go"
}
fmt.Println(result) // Output: GoGoGoGoGo
Если требуется объединить много строк, рекомендуется использовать
strings.Builder. Это более эффективный способ, так как Builder работает с буфером и избегает лишних аллокаций.import "strings"
func main() {
var builder strings.Builder
for i := 0; i < 5; i++ {
builder.WriteString("Go")
}
fmt.Println(builder.String()) // Output: GoGoGoGoGo
}
Go строки поддерживают Unicode, поэтому сложение строк корректно работает с многобайтовыми символами.
s1 := "Привет"
s2 := "Мир"
result := s1 + " " + s2
fmt.Println(result) // Output: Привет Мир
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Go имеет встроенный, автоматический сборщик мусора, поэтому разработчик не управляет памятью вручную. Однако понимание его работы важно:
- GC запускается в фоновом режиме.
- Поддерживается пауза менее миллисекунды для большинства случаев (начиная с Go 1.8 и выше).
- Поведение GC можно настраивать через переменную окружения GOGC.
Сборщик ориентирован на низкую задержку, даже если это немного снижает throughput.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Это гибкий и мощный инструмент для работы с последовательностями элементов. Они предоставляют более высокоуровневый интерфейс для работы с массивами. Рассмотрим, как с ними работать, почему они нужны и какие операции можно выполнять.
Это динамическая последовательность элементов одного типа, которая предоставляет доступ к части или всем элементам массива без копирования данных. Он содержит три компонента:
Указатель на массив.
Длина (количество элементов в слайсе).
Ёмкость (максимальное количество элементов, которые могут быть включены в слайс без перераспределения памяти).
Слайсы позволяют работать с массивами более гибко:
В отличие от массивов, длина слайса может изменяться.
Слайсы можно передавать в функции и возвращать из них, не копируя данные.
Предоставляют множество встроенных функций для работы с последовательностями данных.
Из массива
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // слайс содержит элементы {2, 3, 4}
Используя make
slice := make([]int, 5) // создаёт слайс длиной и ёмкостью 5, заполненный нулями
Литерал слайса
slice := []int{1, 2, 3, 4, 5} Доступ к элементам
fmt.Println(slice[0]) // выводит первый элемент слайса
Изменение элементов
slice[1] = 10 // изменяет второй элемент слайса
Добавление элементов
slice = append(slice, 6, 7) // добавляет элементы 6 и 7 к слайсу
Срезка (slicing)
newSlice := slice[1:3] // создаёт новый слайс с элементами с 1-го по 3-й
Рассмотрим пример функции, которая добавляет элемент в слайс и возвращает новый слайс
package main
import "fmt"
func main() {
nums := []int{1, 2, 3}
nums = append(nums, 4) // добавление элемента
fmt.Println(nums) // выводит [1, 2, 3, 4]
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
- Основной контекст, используемый как корень.
2. context.WithCancel:
- Позволяет отменить выполнение всех дочерних контекстов.
3. context.WithTimeout:
- Устанавливает лимит времени на выполнение операций.
4. context.WithValue:
- Передача ключ-значений между горутинами.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3🔥1
Объектно-ориентированная модель отличается от традиционных ООП-языков, таких как C# или Java. Нет классов и наследования в привычном понимании. Вместо этого используются структуры (structs) и интерфейсы для реализации основных принципов ООП: инкапсуляции, композиции и полиморфизма.
Служат аналогом классов. Они позволяют объединять данные в логически связанные группы.
type Person struct {
Name string
Age int
}Могут быть определены для структур, что позволяет связывать функции с типами.
func (p Person) Greet() {
fmt.Printf("Hello, my name is %s\n", p.Name)
}Достигается через модификаторы доступа на уровне пакета. Поля и методы, начинающиеся с заглавной буквы, экспортируемые (public), остальные — нет (private).
type Person struct {
name string // неэкспортируемое поле
Age int // экспортируемое поле
}Go не поддерживает классическое наследование. Вместо этого используется композиция для включения функциональности одного типа в другой.
type Employee struct {
Person
Position string
}Используются для определения поведения. Типы могут реализовывать интерфейсы неявно, просто предоставляя методы, указанные в интерфейсе.
type Greeter interface {
Greet()
}
func SayHello(g Greeter) {
g.Greet()
}
type Person struct {
Name string
}
func (p Person) Greet() {
fmt.Printf("Hello, my name is %s\n", p.Name)
}
func main() {
p := Person{Name: "John"}
SayHello(p)
}Достигается через интерфейсы. Любой тип, который реализует интерфейс, может быть использован вместо него.
type Greeter interface {
Greet()
}
func SayHello(g Greeter) {
g.Greet()
}
type Robot struct {
ID string
}
func (r Robot) Greet() {
fmt.Printf("Greetings, I am robot %s\n", r.ID)
}
func main() {
p := Person{Name: "John"}
r := Robot{ID: "XJ-9"}
SayHello(p)
SayHello(r)
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
1💊7🤔1
Это фундаментальные концепции, используемые в операционных системах для управления выполнением программ. Хотя они тесно связаны, между ними есть ключевые различия:
Это экземпляр выполняющейся программы. Процесс имеет собственное изолированное адресное пространство памяти, что означает, что память, которую использует один процесс, не может быть напрямую доступна другому процессу. Каждый процесс предоставляет ресурсы, необходимые для выполнения программы, включая память, дескрипторы файлов, и переменные среды. Процессы изолированы друг от друга, что повышает безопасность и устойчивость системы в целом, поскольку сбой в одном процессе обычно не влияет на другие процессы. Однако эта изоляция требует больших затрат ресурсов при переключении между процессами и при их создании.
Это более легковесная единица выполнения, которая существует внутри процесса. Все потоки внутри одного процесса делят одно и то же адресное пространство памяти и системные ресурсы, такие как файловые дескрипторы. Это позволяет потокам более эффективно общаться друг с другом, поскольку они могут обмениваться данными без использования специальных механизмов межпроцессного взаимодействия. Потоки идеально подходят для выполнения задач, которые могут быть эффективно распараллелены, поскольку они позволяют программе выполнять множество операций одновременно. Однако, поскольку потоки делят память, разработчику необходимо тщательно управлять доступом к общим данным, чтобы избежать условий гонки и других проблем синхронизации.
Процессы изолированы друг от друга, в то время как потоки делят состояние и ресурсы внутри одного процесса.
Каждый процесс имеет собственное адресное пространство, в то время как все потоки внутри процесса делят его адресное пространство.
Создание нового процесса более ресурсоемко, чем создание потока внутри существующего процесса.
Взаимодействие между процессами требует использования межпроцессного взаимодействия (IPC), такого как сокеты, разделяемая память, очереди сообщений и т. д. Потоки внутри процесса могут общаться друг с другом напрямую через общую память.
Ошибка в одном процессе обычно не влияет на другие процессы, но ошибка в одном потоке может привести к сбою всего процесса.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
В Go параметры по умолчанию передаются по значению. Это значит, что функция получает копию переменной, и любые изменения внутри функции не повлияют на оригинал.
Однако:
- Если передаётся указатель (*T), слайс, карта или канал, то содержимое может быть изменено.
- Структуры копируются целиком, если не передаются по указателю.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Это технология, используемая для изменения сетевых адресов в заголовках пакетов данных, которые проходят через маршрутизатор или межсетевой экран. Она позволяет нескольким устройствам в локальной сети использовать один и тот же публичный IP-адрес для выхода в интернет.
Фиксированный сопоставление: Один внутренний IP-адрес сопоставляется с одним внешним IP-адресом. Используется, когда необходимо, чтобы устройство в локальной сети всегда было доступно под одним и тем же публичным IP-адресом. Например Веб-сервер, который должен быть доступен из интернета под фиксированным IP-адресом.
Внутренние IP-адреса сопоставляются с пулом внешних IP-адресов. Когда внутреннее устройство инициирует соединение с интернетом, ему временно присваивается один из доступных внешних IP-адресов. Например, локальная сеть с большим количеством устройств, где не требуется фиксированный внешний IP-адрес для каждого устройства.
Несколько внутренних IP-адресов могут использовать один внешний IP-адрес, но различаются по номерам портов. Каждый внутренний IP-адрес и порт сопоставляется с уникальным внешним портом. Например, Домашние или офисные сети, где множество устройств выходят в интернет через один публичный IP-адрес.
IPv4-адресов недостаточно для всех устройств, и NAT позволяет использовать один публичный IP-адрес для множества устройств.
Внутренние IP-адреса не видны извне, что усложняет потенциальным злоумышленникам попытки атак на внутренние устройства.
NAT позволяет администрировать и контролировать сетевой трафик, предоставляя возможности для управления доступом и приоритизацией трафика.
Когда устройство в локальной сети (например, компьютер с IP-адресом 192.168.1.10) инициирует соединение с устройством в интернете, NAT изменяет исходящий IP-адрес и порт на внешний IP-адрес маршрутизатора и уникальный номер порта.
Когда ответный пакет возвращается, NAT использует таблицу сопоставлений, чтобы определить, к какому внутреннему устройству направить пакет, и изменяет внешний IP-адрес и порт обратно на внутренний IP-адрес и порт.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
2. Специальные структуры: вместо обычных карт можно использовать потокобезопасные реализации, такие как sync.Map.
3. Избегание гонок данных: убедитесь, что к карте обращаются только из одного потока или через контролируемую синхронизацию.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
В Go
sync.WaitGroup используется для синхронизации выполнения горутин. Она позволяет основной горутине (или любой другой горутине) ждать завершения группы горутин перед продолжением работы. Это особенно полезно, когда нужно убедиться, что все фоновые задачи завершены до выполнения дальнейших действий.Увеличивает (или уменьшает) счетчик горутин на заданное значение
delta.Обычно вызывается до запуска горутин, чтобы установить количество горутин, которые нужно дождаться.
Уменьшает счетчик горутин на 1.
Вызывается горутиной, когда она завершает свою работу.
Блокирует выполнение до тех пор, пока счетчик горутин не станет равен нулю.
Обычно вызывается основной горутиной для ожидания завершения всех горутин.
Мы используем
WaitGroup для ожидания завершения нескольких горутин.package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // Уменьшает счетчик на 1 при завершении работы горутины
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1) // Увеличивает счетчик горутин на 1
go worker(i, &wg)
}
wg.Wait() // Ожидает завершения всех горутин
fmt.Println("All workers done")
}
worker.WaitGroup увеличивается на 1 перед запуском каждой горутины с помощью wg.Add(1).wg.Done() при завершении, уменьшая счетчик на 1.wg.Wait(), блокируясь до тех пор, пока все горутины не завершат свою работу.Позволяет основной горутине дождаться завершения всех запущенных горутин, что особенно важно для корректного завершения программы или выполнения зависимых задач.
Гарантирует, что основная горутина не завершит выполнение программы до того, как завершатся все горутины, предотвращая возможные дедлоки или незавершенные операции.
Позволяет легко управлять множеством горутин, не требуя сложной логики для отслеживания их завершения.
Без использования
WaitGroup основной поток может завершиться до завершения всех горутин, что приведет к неполной обработке данных. В этом примере использование time.Sleep для ожидания является ненадежным и не гарантирует завершение всех горутин. Вместо этого правильное использование WaitGroup обеспечивает корректное завершение всех задач.package main
import (
"fmt"
"time"
)
func worker(id int) {
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
for i := 1; i <= 5; i++ {
go worker(i)
}
time.Sleep(2 * time.Second) // Это не гарантирует завершение всех горутин
fmt.Println("All workers done")
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Каналы потокобезопасны для отправки и получения данных, но передаваемые объекты должны быть неизменяемыми для предотвращения гонок.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2