{[3][]int{{1}}, false}, // incomparable array
{[1 << 12]byte{}, true},
{[1 << 12]byte{1}, false},
+ {[3]Value{}, true},
+ {[3]Value{{}, ValueOf(0), {}}, false},
// Chan
{(chan string)(nil), true},
{make(chan string), false},
{struct{ p *int }{new(int)}, false}, // direct pointer struct
{struct{ s []int }{}, true}, // incomparable struct
{struct{ s []int }{[]int{1}}, false}, // incomparable struct
+ {struct{ Value }{}, true},
+ {struct{ Value }{ValueOf(0)}, false},
// UnsafePointer
{(unsafe.Pointer)(nil), true},
{(unsafe.Pointer)(new(int)), false},
if !Zero(TypeOf(tt.x)).IsZero() {
t.Errorf("%d: IsZero(Zero(TypeOf((%s)(%+v)))) is false", i, x.Kind(), tt.x)
}
+
+ p := New(x.Type()).Elem()
+ p.Set(x)
+ p.SetZero()
+ if !p.IsZero() {
+ t.Errorf("%d: IsZero((%s)(%+v)) is true after SetZero", i, p.Kind(), tt.x)
+ }
}
func() {
}
}
+func BenchmarkSetZero(b *testing.B) {
+ source := ValueOf(new(struct {
+ Bool bool
+ Int int64
+ Uint uint64
+ Float float64
+ Complex complex128
+ Array [4]Value
+ Chan chan Value
+ Func func() Value
+ Interface interface{ String() string }
+ Map map[string]Value
+ Pointer *Value
+ Slice []Value
+ String string
+ Struct Value
+ })).Elem()
+
+ for i := 0; i < source.NumField(); i++ {
+ name := source.Type().Field(i).Name
+ value := source.Field(i)
+ zero := Zero(value.Type())
+ b.Run(name+"/Direct", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ value.SetZero()
+ }
+ })
+ b.Run(name+"/CachedZero", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ value.Set(zero)
+ }
+ })
+ b.Run(name+"/NewZero", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ value.Set(Zero(value.Type()))
+ }
+ })
+ }
+}
+
func TestInterfaceExtraction(t *testing.T) {
var s struct {
W io.Writer
}
return true
default:
- // This should never happens, but will act as a safeguard for
- // later, as a default value doesn't makes sense here.
+ // This should never happen, but will act as a safeguard for later,
+ // as a default value doesn't makes sense here.
panic(&ValueError{"reflect.Value.IsZero", v.Kind()})
}
}
+// SetZero sets v to be the zero value of v's type.
+// It panics if CanSet returns false.
+func (v Value) SetZero() {
+ v.mustBeAssignable()
+ switch v.kind() {
+ case Bool:
+ *(*bool)(v.ptr) = false
+ case Int:
+ *(*int)(v.ptr) = 0
+ case Int8:
+ *(*int8)(v.ptr) = 0
+ case Int16:
+ *(*int16)(v.ptr) = 0
+ case Int32:
+ *(*int32)(v.ptr) = 0
+ case Int64:
+ *(*int64)(v.ptr) = 0
+ case Uint:
+ *(*uint)(v.ptr) = 0
+ case Uint8:
+ *(*uint8)(v.ptr) = 0
+ case Uint16:
+ *(*uint16)(v.ptr) = 0
+ case Uint32:
+ *(*uint32)(v.ptr) = 0
+ case Uint64:
+ *(*uint64)(v.ptr) = 0
+ case Uintptr:
+ *(*uintptr)(v.ptr) = 0
+ case Float32:
+ *(*float32)(v.ptr) = 0
+ case Float64:
+ *(*float64)(v.ptr) = 0
+ case Complex64:
+ *(*complex64)(v.ptr) = 0
+ case Complex128:
+ *(*complex128)(v.ptr) = 0
+ case String:
+ *(*string)(v.ptr) = ""
+ case Slice:
+ *(*unsafeheader.Slice)(v.ptr) = unsafeheader.Slice{}
+ case Interface:
+ *(*[2]unsafe.Pointer)(v.ptr) = [2]unsafe.Pointer{}
+ case Chan, Func, Map, Pointer, UnsafePointer:
+ *(*unsafe.Pointer)(v.ptr) = nil
+ case Array, Struct:
+ typedmemclr(v.typ, v.ptr)
+ default:
+ // This should never happen, but will act as a safeguard for later,
+ // as a default value doesn't makes sense here.
+ panic(&ValueError{"reflect.Value.SetZero", v.Kind()})
+ }
+}
+
// Kind returns v's Kind.
// If v is the zero Value (IsValid returns false), Kind returns Invalid.
func (v Value) Kind() Kind {