Оператор "квадратные скобки" (
[]
) при применении к строке используется для доступа к отдельным байтам в этой строке. Строки представлены как последовательности байтов, и оператор []
позволяет получить байт по указанному индексу. package main
import (
"fmt"
)
func main() {
str := "hello"
// Получаем байт по индексу
firstByte := str[0]
// Выводим байт и его символ
fmt.Printf("Первый байт: %d\n", firstByte) // Выводит: 104
fmt.Printf("Первый символ: %c\n", firstByte) // Выводит: h
}
В этой строке кода мы получаем байт, расположенный по индексу
0
в строке str
. В данном случае это байт, соответствующий символу 'h'.firstByte := str[0]
Здесь мы выводим байт в виде целого числа. Поскольку символ 'h' имеет ASCII-код 104, вывод будет
104
.fmt.Printf("Первый байт: %d\n", firstByte)
Мы также можем вывести байт как символ, используя формат
%c
. Это отобразит символ 'h'.fmt.Printf("Первый символ: %c\n", firstByte)
Важно понимать, что строки являются последовательностями байтов, а не символов. Это означает, что доступ по индексу с помощью
[]
дает байт, а не руну (rune). Если строка содержит многобайтовые символы (например, символы Unicode), то доступ по индексу может вернуть только один из байтов, составляющих символ.package main
import (
"fmt"
)
func main() {
str := "Привет"
// Получаем байт по индексу
firstByte := str[0]
// Выводим байт и его символ
fmt.Printf("Первый байт: %d\n", firstByte) // Выводит: 208
fmt.Printf("Первый символ: %c\n", firstByte) // Выводит: � (неполный символ)
}
Для корректной работы с многобайтовыми символами (рунами) в строках используется преобразование строки в срез рун
package main
import (
"fmt"
)
func main() {
str := "Привет"
// Преобразуем строку в срез рун
runes := []rune(str)
// Получаем руну по индексу
firstRune := runes[0]
// Выводим руну и её символ
fmt.Printf("Первая руна: %d\n", firstRune) // Выводит: 1055 (код Unicode для 'П')
fmt.Printf("Первый символ: %c\n", firstRune) // Выводит: П
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Срезать можно через оператор [start:end]:
1. Новый слайс будет ссылаться на тот же массив, что и оригинал.
2. Изменение элементов в новом слайсе отразится на оригинале.
3. Если указать только start или end, будут использованы начальные или конечные значения: slice[start:] или slice[:end].
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Массивы и слайсы могут использоваться для хранения последовательности элементов одного типа. Когда вы "подставляете" переменную в массив или слайс, вы просто присваиваете значение этой переменной одному из элементов массива или слайса.
Пример с массивом
package main
import "fmt"
func main() {
// Создаем массив из 5 целых чисел
var arr [5]int
// Создаем переменную и присваиваем ей значение
x := 10
// Подставляем переменную в массив
arr[0] = x
// Выводим массив
fmt.Println(arr) // Выводит: [10 0 0 0 0]
}
Это создает массив
arr
из 5 целых чисел, все элементы которого инициализируются значением 0
.var arr [5]int
Создаем переменную
x
и присваиваем ей значение 10
.x := 10
Присваиваем значение переменной
x
первому элементу массива arr
.arr[0] = x
Выводит содержимое массива, показывая, что первый элемент массива теперь равен
10
, а остальные элементы остаются нулями.fmt.Println(arr)
Пример со слайсом
package main
import "fmt"
func main() {
// Создаем слайс из 3 целых чисел
slice := make([]int, 3)
// Создаем переменную и присваиваем ей значение
x := 20
// Подставляем переменную в слайс
slice[1] = x
// Выводим слайс
fmt.Println(slice) // Выводит: [0 20 0]
}
Это создает слайс
slice
из 3 целых чисел, все элементы которого инициализируются значением 0
.slice := make([]int, 3)
Создаем переменную
x
и присваиваем ей значение 20
.x := 20
Присваиваем значение переменной
x
второму элементу слайса slice
.slice[1] = x
Выводит содержимое слайса, показывая, что второй элемент слайса теперь равен
20
, а остальные элементы остаются нулями.fmt.Println(slice)
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊2👍1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
В Go обычный
map
не потокобезопасен. Если несколько горутин одновременно записывают в map
, возникнет ошибка "fatal error: concurrent map writes". Решение: использовать синхронизацию через
sync.Mutex
, sync.RWMutex
или sync.Map
. Блокируем доступ на запись и чтение через
sync.Mutex
. package main
import (
"fmt"
"sync"
)
type SafeMap struct {
mu sync.Mutex
m map[string]int
}
func (s *SafeMap) Set(key string, value int) {
s.mu.Lock() // Блокируем доступ
defer s.mu.Unlock()
s.m[key] = value
}
func (s *SafeMap) Get(key string) int {
s.mu.Lock() // Блокируем на чтение
defer s.mu.Unlock()
return s.m[key]
}
func main() {
safeMap := SafeMap{m: make(map[string]int)}
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
safeMap.Set(fmt.Sprintf("key%d", i), i)
}(i)
}
wg.Wait()
fmt.Println("Готово:", safeMap.Get("key5")) // Получаем значение без гонок данных
}
sync.RWMutex
позволяет нескольким горутинам читать одновременно, но блокирует запись. type SafeMap struct {
mu sync.RWMutex
m map[string]int
}
func (s *SafeMap) Set(key string, value int) {
s.mu.Lock() // Блокируем только на запись
defer s.mu.Unlock()
s.m[key] = value
}
func (s *SafeMap) Get(key string) int {
s.mu.RLock() // Разрешаем множественное чтение
defer s.mu.RUnlock()
return s.m[key]
}
sync.Map
из стандартной библиотеки уже потокобезопасен, но работает немного медленнее обычного map
из-за внутренних механизмов. package main
import (
"fmt"
"sync"
)
func main() {
var m sync.Map
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
m.Store(i, i*10) // Потокобезопасная запись
}(i)
}
wg.Wait()
val, ok := m.Load(5) // Потокобезопасное чтение
if ok {
fmt.Println("Значение:", val)
}
}
Использование канала (`chan`) вместо `map`
Вместо
map
можно передавать данные через канал (chan
), если логика позволяет. package main
import (
"fmt"
)
func main() {
ch := make(chan map[string]int, 1)
ch <- make(map[string]int)
go func() {
m := <-ch
m["key"] = 42
ch <- m
}()
m := <-ch
fmt.Println(m["key"]) // 42
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Обобщённое (generics) программирование включает:
- Параметрические типы — функции и структуры с типами-плейсхолдерами.
- Ограничения (where, extends, : T) — накладывают требования на типы.
- Обобщённые интерфейсы и классы.
- Type erasure — скрытие конкретного типа при сохранении поведения. Generics позволяют писать универсальный, повторно используемый код с типовой безопасностью.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Слайсы представляют собой мощный и гибкий инструмент для работы с последовательностями элементов. Основаны на массивах, но они предоставляют более удобный и динамичный способ работы с данными.
Указатель на первый элемент массива, на который ссылается слайс.
Количество элементов, доступных в слайсе.
Максимальное количество элементов, которое может содержать слайс без перераспределения памяти.
Можно представить в виде структуры
type slice struct {
ptr *ElementType // Указатель на базовый массив
len int // Длина
cap int // Емкость
}
Можно создать из массива, указав диапазон элементов:
package main
import "fmt"
func main() {
arr := [5]int{1, 2, 3, 4, 5}
slice := arr[1:4] // Слайс содержит элементы с индексами 1, 2, 3
fmt.Println(slice) // [2 3 4]
}
Позволяет создать слайс определенной длины и емкости:
package main
import "fmt"
func main() {
slice := make([]int, 3, 5) // Слайс длиной 3 и емкостью 5
fmt.Println(slice) // [0 0 0]
}
Осуществляется так же, как и к элементам массива:
package main
import "fmt"
func main() {
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice[0]) // 1
slice[1] = 10
fmt.Println(slice) // [1 10 3 4 5]
}
Для этого используется функция
append
package main
import "fmt"
func main() {
slice := []int{1, 2, 3}
slice = append(slice, 4, 5) // Добавляем элементы 4 и 5 в конец слайса
fmt.Println(slice) // [1 2 3 4 5]
}
Можно создавать новые слайсы на основе существующих
package main
import "fmt"
func main() {
slice := []int{1, 2, 3, 4, 5}
subSlice := slice[1:4] // Слайс содержит элементы с индексами 1, 2, 3
fmt.Println(subSlice) // [2 3 4]
}
Для этого используется функция
copy
package main
import "fmt"
func main() {
src := []int{1, 2, 3}
dst := make([]int, len(src))
copy(dst, src)
fmt.Println(dst) // [1 2 3]
}
Могут автоматически изменять свою емкость при добавлении новых элементов с помощью
append
. Когда емкость текущего массива недостаточна для добавления новых элементов, создается новый массив с большей емкостью, в который копируются существующие элементы.package main
import "fmt"
func main() {
slice := make([]int, 3, 5)
fmt.Println("Before append:", slice, "Len:", len(slice), "Cap:", cap(slice))
slice = append(slice, 1, 2, 3)
fmt.Println("After append:", slice, "Len:", len(slice), "Cap:", cap(slice))
slice = append(slice, 4)
fmt.Println("After another append:", slice, "Len:", len(slice), "Cap:", cap(slice))
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
1. Read Uncommitted – транзакция читает несохраненные изменения других транзакций (грязное чтение).
2. Read Committed – транзакция видит только сохраненные изменения других транзакций.
3. Repeatable Read – транзакция видит одинаковые данные при повторных запросах, но возможны фантомные чтения.
4. Serializable – полный контроль над данными, транзакции выполняются последовательно, но снижается производительность.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍1
Массивы представляют собой фиксированную последовательность элементов одного типа. Являются основополагающей структурой данных, на базе которой строятся более сложные структуры, такие как слайсы. Рассмотрим, как устроены массивы, их особенности, а также сравнение с другими структурами данных.
Размер массива задается при его объявлении и не может изменяться во время выполнения программы.
Все элементы массива имеют один и тот же тип.
В отличие от слайсов, массивы хранят свои элементы в непрерывном блоке памяти.
С указанием типа элементов и фиксированного размера. Это объявление создает массив из пяти целых чисел, инициализированных нулями.
var arr [5]int
Массивы могут быть инициализированы при объявлении
arr := [5]int{1, 2, 3, 4, 5}
Можно также инициализировать массив частично, оставив остальные элементы равными нулям:
arr := [5]int{1, 2}
Осуществляется с использованием индексов, начиная с 0
fmt.Println(arr[0]) // 1
arr[1] = 10
fmt.Println(arr[1]) // 10
Фиксирована и задается при его объявлении. Ее можно получить с помощью функции
len
fmt.Println(len(arr)) // 5
При присваивании одного массива другому копируются все элементы:
arr1 := [5]int{1, 2, 3, 4, 5}
arr2 := arr1
arr2[0] = 10
fmt.Println(arr1) // [1 2 3 4 5]
fmt.Println(arr2) // [10 2 3 4 5]
При этом копируется весь массив:
func modifyArray(a [5]int) {
a[0] = 10
}
arr := [5]int{1, 2, 3, 4, 5}
modifyArray(arr)
fmt.Println(arr) // [1 2 3 4 5]
Массивы имеют фиксированный размер, тогда как слайсы динамичны.
Массивы могут быть более производительными для небольших коллекций данных из-за отсутствия накладных расходов на управление динамическими данными.
Использование массивов
package main
import (
"fmt"
)
func main() {
// Объявление и инициализация массива
arr := [5]int{1, 2, 3, 4, 5}
// Доступ к элементам
fmt.Println("First element:", arr[0]) // First element: 1
// Изменение элементов
arr[1] = 10
fmt.Println("Modified array:", arr) // Modified array: [1 10 3 4 5]
// Длина массива
fmt.Println("Length of array:", len(arr)) // Length of array: 5
// Копирование массива
arr2 := arr
arr2[0] = 20
fmt.Println("Original array:", arr) // Original array: [1 10 3 4 5]
fmt.Println("Copied array:", arr2) // Copied array: [20 10 3 4 5]
// Передача массива в функцию
modifyArray(arr)
fmt.Println("Array after modifyArray call:", arr) // Array after modifyArray call: [1 10 3 4 5]
}
func modifyArray(a [5]int) {
a[0] = 10
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2