package atomicvalue
import "sync/atomic"
type AtomicValue[T any] struct {
v atomic.Value
}
func (av *AtomicValue[T]) Load() T {
if v := av.v.Load(); v != nil {
return v.(T)
} else {
var v T
return v
}
}
func (av *AtomicValue[T]) Store(value T) {
av.v.Store(value)
}
func (av *AtomicValue[T]) CompareAndSwap(old, new T) bool {
return av.v.CompareAndSwap(old, new)
}
func (av *AtomicValue[T]) Swap(new T) (old T) {
old = av.Load()
av.Store(new)
return old
}
I wrap the atomic.Value to a generic type. I handled the zero value in Load() function, but I can't store nil.
type MyInterface interface{
One()
Two()
Three()
}
var value atomicvalue.AtomicValue[MyInterface]
bar:=&MyStruct{} // MyStruct implements MyInterface
value.store(bar) // ok
value.store(nil) // panic there
When I store a nil, there will be a panic:
panic: sync/atomic: store of nil value into Value
Answers
The panic occurs because the atomic.Value
does not allow storing nil
values. In your AtomicValue
implementation, you're trying to handle the zero value case in the Load
function, but storing nil
directly is not permitted by the atomic.Value
.
To handle nil
values gracefully in your AtomicValue
, you can use a sentinel value to represent nil
. Here's how you can modify your AtomicValue
implementation to handle nil
:
package atomicvalue
import "sync/atomic"
type AtomicValue[T any] struct {
v atomic.Value
}
func (av *AtomicValue[T]) Load() T {
if v := av.v.Load(); v != nil {
return v.(T)
}
// Handle nil case by returning a default value or sentinel value
return zeroValueForTypeT() // Or return your predefined sentinel value
}
func (av *AtomicValue[T]) Store(value T) {
// If value is nil, store a sentinel value instead
if value == nil {
value = zeroValueForTypeT() // Or use your predefined sentinel value
}
av.v.Store(value)
}
func (av *AtomicValue[T]) CompareAndSwap(old, new T) bool {
return av.v.CompareAndSwap(old, new)
}
func (av *AtomicValue[T]) Swap(new T) (old T) {
old = av.Load()
av.Store(new)
return old
}
// Define a function to return zero value or sentinel value for type T
func zeroValueForTypeT() T {
// Return appropriate zero value or sentinel value for type T
}
In this modified implementation, when storing a nil
value, you replace it with a sentinel value that represents nil
. Similarly, in the Load
function, you handle the case where the stored value is the sentinel value and return nil
accordingly.
Ensure that zeroValueForTypeT()
returns an appropriate zero value or sentinel value for the type T
. This approach allows you to gracefully handle nil
values without causing a panic.