Ответ на этот вопрос требует понимания принципов конкурентности в Go и работы с памятью:
Да, можно, но с важными оговорками
buf := make([]byte, 1024)
// Безопасно в нескольких горутинах
go func() {
fmt.Println(buf[0]) // Чтение
}()
go func() {
fmt.Println(buf[1]) // Чтение
}()
var bufPool = sync.Pool{
New: func() interface{} {
return make([]byte, 1024)
}
}
// Безопасно - каждая горутина получает свой буфер
go func() {
b := bufPool.Get().([]byte)
defer bufPool.Put(b)
// работа с b
}()
buf := make([]byte, 10)
go func() {
buf[0] = 1 // Опасность гонки данных!
}()
go func() {
buf[1] = 2 // Опасность гонки данных!
}()
buf := make([]byte, 0, 10)
go func() {
buf = append(buf, 1) // Гонка данных при изменении slice header!
}()
var (
buf = make([]byte, 1024)
bufMu sync.Mutex
)
go func() {
bufMu.Lock()
buf[0] = 1
bufMu.Unlock()
}()
buf := make([]byte, 2048)
go func() {
part := buf[:1024] // Первая половина
// Работа с part
}()
go func() {
part := buf[1024:] // Вторая половина
// Работа с part
}()
bufChan := make(chan []byte, 1)
bufChan <- make([]byte, 1024)
go func() {
b := <-bufChan
b[0] = 1 // Эксклюзивный доступ
bufChan <- b
}()
// Плохо для производительности, но безопасно
var globalBuf struct {
sync.Mutex
data []byte
}
// Лучше - локальные буферы + редкая синхронизация
func worker(localBuf []byte) {
// ...
}
использовать общий буфер в нескольких горутинах можно, но только либо для чтения, либо с надлежащей синхронизацией. Для записи безопаснее выделять отдельные буферы или части буфера. Всегда проверяйте код на гонки данных с помощью go run -race
.