Ответ
Нет, по умолчанию структуры в Go не являются потокобезопасными. Если несколько горутин одновременно обращаются к данным одной и той же структуры, и хотя бы одна из них выполняет запись, возникает состояние гонки (data race), что приводит к непредсказуемому поведению программы.
Go придерживается принципа "не общайтесь через разделяемую память, а разделяйте память через общение". Однако для ситуаций, где необходим прямой доступ к общим данным, существуют механизмы синхронизации:
- Мьютексы (
sync.Mutex
иsync.RWMutex
): Самый распространенный способ.Mutex
предоставляет эксклюзивный доступ, аRWMutex
позволяет множество читателей или одного писателя. - Каналы (channels): Идиоматичный способ Go для безопасной передачи данных между горутинами.
- Атомарные операции (
sync/atomic
): Для простых операций над примитивными типами (например, инкремент счетчика), которые выполняются без блокировок и являются более производительными.
Пример с sync.Mutex
:
type SafeCounter struct {
mu sync.Mutex
count int
}
func (c *SafeCounter) Increment() {
c.mu.Lock() // Блокируем доступ для других горутин
defer c.mu.Unlock() // Гарантируем разблокировку в конце функции
c.count++
}
func (c *SafeCounter) Value() int {
c.mu.Lock()
defer c.mu.Unlock()
return c.count
}