Ответ 1
Единственными вещами, которые гарантированно являются атомарными в go, являются операции в sync.atomic.
Итак, если вы хотите быть уверенным, что вам нужно будет сделать блокировку, например sync.Mutex или использовать один из атомных примитивов. Я не рекомендую использовать атомарные примитивы, хотя вам придется использовать их везде, где вы используете указатель, и их трудно получить.
Использование мьютекса в порядке go style - вы можете определить функцию для быстрого возврата текущего указателя с блокировкой, например, что-то вроде
import "sync"
var secretPointer *int
var pointerLock sync.Mutex
func CurrentPointer() *int {
pointerLock.Lock()
defer pointerLock.Unlock()
return secretPointer
}
func SetPointer(p *int) {
pointerLock.Lock()
secretPointer = p
pointerLock.Unlock()
}
Эти функции возвращают копию указателя на их клиентов, которые останутся постоянными, даже если главный указатель будет изменен. Это может быть или не быть приемлемым в зависимости от времени, требующего вашего требования. Этого должно быть достаточно, чтобы избежать любого поведения undefined - сборщик мусора гарантирует, что указатели остаются действительными во все времена, даже если указанная память больше не используется вашей программой.
Альтернативный подход состоял бы в том, чтобы сделать доступ только для указателя из одной процедуры и использовать каналы для управления, которые подталкивают к выполнению действий. Это будет считаться более идиоматичным, но может не соответствовать вашему приложению.
Обновление
Вот пример, показывающий, как использовать atomic.SetPointer
. Это довольно уродливо из-за использования unsafe.Pointer
. Однако unsafe.Pointer
делает компиляцию ни к чему, поэтому стоимость исполнения невелика.
import (
"fmt"
"sync/atomic"
"unsafe"
)
type Struct struct {
p unsafe.Pointer // some pointer
}
func main() {
data := 1
info := Struct{p: unsafe.Pointer(&data)}
fmt.Printf("info is %d\n", *(*int)(info.p))
otherData := 2
atomic.StorePointer(&info.p, unsafe.Pointer(&otherData))
fmt.Printf("info is %d\n", *(*int)(info.p))
}