Нарезка (slicing) — это создание нового слайса, который указывает на подмножество элементов исходного слайса. Этот процесс включает указание начального и конечного индексов для создания нового слайса. Несмотря на свою простоту, slicing имеет несколько нюансов и потенциальных подводных камней, которые важно учитывать.
Синтаксис
newSlice := originalSlice[start:end]
start: начальный индекс (включительно).end: конечный индекс (исключительно).Пример
package main
import "fmt"
func main() {
original := []int{1, 2, 3, 4, 5}
newSlice := original[1:4] // Элементы с индексами 1, 2 и 3
fmt.Println(newSlice) // [2 3 4]
}
При нарезке слайса важно, чтобы индексы
start и end были в пределах длины исходного слайса. Нарушение этого правила приведет к панике (runtime panic).package main
import "fmt"
func main() {
original := []int{1, 2, 3, 4, 5}
// Это вызовет панику: runtime error: slice bounds out of range
// newSlice := original[1:6]
// Правильное использование
newSlice := original[1:5]
fmt.Println(newSlice) // [2 3 4 5]
}
Слайсы в Go работают как ссылки на массивы. Это означает, что если вы модифицируете элементы нового слайса, то изменения отразятся и в исходном слайсе.
package main
import "fmt"
func main() {
original := []int{1, 2, 3, 4, 5}
newSlice := original[1:4]
newSlice[0] = 20
fmt.Println("Original:", original) // [1 20 3 4 5]
fmt.Println("New Slice:", newSlice) // [20 3 4]
}
Длина нового слайса определяется как
end - start. Емкость нового слайса определяется как cap(original) - start.package main
import "fmt"
func main() {
original := []int{1, 2, 3, 4, 5}
newSlice := original[1:4]
fmt.Println("New Slice Length:", len(newSlice)) // 3
fmt.Println("New Slice Capacity:", cap(newSlice)) // 4
}
Если нужно создать независимую копию слайса, следует использовать функцию
copy, чтобы изменения в новом слайсе не влияли на исходный.package main
import "fmt"
func main() {
original := []int{1, 2, 3, 4, 5}
newSlice := make([]int, 3)
copy(newSlice, original[1:4])
newSlice[0] = 20
fmt.Println("Original:", original) // [1 2 3 4 5]
fmt.Println("New Slice:", newSlice) // [20 3 4]
}
Полная форма нарезки позволяет явно указать емкость нового слайса:
newSlice := original[start:end:max
Это полезно, когда вы хотите контролировать емкость нового слайса.
package main
import "fmt"
func main() {
original := []int{1, 2, 3, 4, 5}
newSlice := original[1:3:4]
fmt.Println("New Slice:", newSlice) // [2 3]
fmt.Println("New Slice Capacity:", cap(newSlice)) // 3
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Это гибкий и мощный инструмент для работы с последовательностями элементов. Они предоставляют более высокоуровневый интерфейс для работы с массивами. Рассмотрим, как с ними работать, почему они нужны и какие операции можно выполнять.
Это динамическая последовательность элементов одного типа, которая предоставляет доступ к части или всем элементам массива без копирования данных. Он содержит три компонента:
Указатель на массив.
Длина (количество элементов в слайсе).
Ёмкость (максимальное количество элементов, которые могут быть включены в слайс без перераспределения памяти).
Слайсы позволяют работать с массивами более гибко:
В отличие от массивов, длина слайса может изменяться.
Слайсы можно передавать в функции и возвращать из них, не копируя данные.
Предоставляют множество встроенных функций для работы с последовательностями данных.
Из массива
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
map? 2. Запись значения: map[key] = value.
3. Удаление ключа: delete(map, key).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🔥1
HAVING — это оператор в SQL, который фильтрует группированные (GROUP BY) данные по агрегатным функциям (SUM, COUNT, AVG, MAX, MIN). WHERE фильтрует отдельные строки до группировки. HAVING фильтрует группы строк после GROUP BY. Теперь посчитаем сумму продаж по категориям и оставим только те, где сумма > 250
SELECT category, SUM(amount) AS total_sales
FROM sales
GROUP BY category
HAVING SUM(amount) > 250;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
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