Ответ
Для обеспечения потокобезопасности слайса в Go используются примитивы синхронизации, такие как sync.Mutex
или sync.RWMutex
. sync.RWMutex
предпочтительнее для сценариев с частыми операциями чтения и редкими операциями записи, так как он позволяет множественным горутинам читать данные одновременно.
Пример реализации потокобезопасного слайса:
type SafeSlice struct {
mu sync.RWMutex
items []string
}
// NewSafeSlice создает новый потокобезопасный слайс.
func NewSafeSlice() *SafeSlice {
return &SafeSlice{
items: make([]string, 0),
}
}
// Append добавляет элемент в слайс, защищая операцию мьютексом.
func (s *SafeSlice) Append(item string) {
s.mu.Lock() // Захватываем блокировку для записи
defer s.mu.Unlock() // Освобождаем блокировку после завершения операции
s.items = append(s.items, item)
}
// Get возвращает элемент по индексу, защищая операцию мьютексом чтения.
// Возвращает элемент и булево значение, указывающее на успешность операции (если индекс в пределах).
func (s *SafeSlice) Get(index int) (string, bool) {
s.mu.RLock() // Захватываем блокировку для чтения
defer s.mu.RUnlock() // Освобождаем блокировку чтения
if index < 0 || index >= len(s.items) {
return "", false // Индекс вне диапазона
}
return s.items[index], true
}
// Len возвращает текущую длину слайса.
func (s *SafeSlice) Len() int {
s.mu.RLock()
defer s.mu.RUnlock()
return len(s.items)
}
// Remove удаляет элемент по индексу.
func (s *SafeSlice) Remove(index int) bool {
s.mu.Lock()
defer s.mu.Unlock()
if index < 0 || index >= len(s.items) {
return false
}
s.items = append(s.items[:index], s.items[index+1:]...)
return true
}
Важные моменты:
- Все операции чтения и записи, изменяющие или обращающиеся к слайсу, должны быть защищены соответствующим мьютексом (
Lock
/Unlock
для записи,RLock
/RUnlock
для чтения). - Используйте
defer
для гарантированного освобождения блокировки, даже если произойдет паника. - Для более сложных сценариев или других структур данных (например, мапов) рассмотрите использование
sync.Map
или паттернов на основе каналов, которые могут предложить более идиоматичные или производительные решения для определенных задач.